Add verification

This commit is contained in:
lemjclarke 2022-03-10 08:43:53 +00:00
parent 12f512057f
commit 93aba9360a
2 changed files with 94 additions and 5 deletions

View File

@ -7,7 +7,9 @@ import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SignableData
import net.corda.core.crypto.SignatureMetadata
import net.corda.core.crypto.sign
import net.corda.core.internal.dependencies
import net.corda.core.transactions.EncryptedTransaction
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.ByteSequence
import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme
import net.corda.serialization.internal.AMQP_P2P_CONTEXT
@ -17,10 +19,10 @@ import net.corda.serialization.internal.amqp.SerializerFactory
class EncryptedTxEnclave {
private val keyPair = Crypto.generateKeyPair("ECDSA_SECP256K1_SHA256")
private val enclaveKeyPair = Crypto.generateKeyPair("ECDSA_SECP256K1_SHA256")
private val signatureMetadata = SignatureMetadata(
platformVersion = 1,
schemeNumberID = Crypto.findSignatureScheme(keyPair.public).schemeNumberID
schemeNumberID = Crypto.findSignatureScheme(enclaveKeyPair.public).schemeNumberID
)
private val serializerFactoriesForContexts = Caffeine.newBuilder()
@ -49,12 +51,12 @@ class EncryptedTxEnclave {
val signedTransaction = ledgerTxModel.signedTransaction
val signableData = SignableData(signedTransaction.id, signatureMetadata)
val transactionSignature = keyPair.sign(signableData)
val transactionSignature = enclaveKeyPair.sign(signableData)
return EncryptedTransaction(
id = signedTransaction.id,
encryptedBytes = ledgerTxBytes,
dependencies = emptySet(),
dependencies = signedTransaction.dependencies,
sigs = listOf(transactionSignature)
)
}
@ -65,6 +67,27 @@ class EncryptedTxEnclave {
clazz = VerifiableTxAndDependencies::class.java,
context = AMQP_P2P_CONTEXT)
// TODO: add verification
val signedTransaction = txAndDependencies.conclaveLedgerTxModel.signedTransaction
signedTransaction.verifyRequiredSignatures()
val dependencies = decryptDependencies(txAndDependencies.dependencies)
dependencies.forEach {
it.verifyRequiredSignatures()
}
val ledgerTransaction = LedgerTxHelper.toLedgerTxInternal(txAndDependencies.conclaveLedgerTxModel, dependencies)
ledgerTransaction.verify()
}
private fun decryptDependencies(dependencies: Set<EncryptedTransaction>): Set<SignedTransaction> {
// simply deserialize for this "mock enclave"
return dependencies.map {
val conclaveLedgerTxModel = serializationFactoryImpl.deserialize(
byteSequence = ByteSequence.of(it.encryptedBytes, 0, it.encryptedBytes.size),
clazz = ConclaveLedgerTxModel::class.java,
context = AMQP_P2P_CONTEXT)
conclaveLedgerTxModel.signedTransaction
}.toSet()
}
}

View File

@ -0,0 +1,66 @@
package com.r3.conclave.encryptedtx.enclave
import com.r3.conclave.encryptedtx.dto.ConclaveLedgerTxModel
import net.corda.core.contracts.CommandWithParties
import net.corda.core.contracts.ComponentGroupEnum
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionResolutionException
import net.corda.core.contracts.TransactionState
import net.corda.core.crypto.SecureHash
import net.corda.core.internal.SerializedStateAndRef
import net.corda.core.serialization.SerializedBytes
import net.corda.core.transactions.LedgerTransaction
import net.corda.core.transactions.SignedTransaction
class LedgerTxHelper {
companion object {
@JvmStatic
fun toLedgerTxInternal(conclaveLedgerTxModel: ConclaveLedgerTxModel, dependencies: Set<SignedTransaction>): LedgerTransaction {
val wireTransaction = conclaveLedgerTxModel.signedTransaction.tx
val dependencyMap = dependencies.associateBy { it.tx.id }
val serializedResolvedInputs = conclaveLedgerTxModel.inputStates.map {
resolveStateRefBinaryComponent(it.ref, dependencyMap) ?: throw TransactionResolutionException(it.ref.txhash)
}
val serializedResolvedReferences = conclaveLedgerTxModel.references.map {
resolveStateRefBinaryComponent(it.ref, dependencyMap) ?: throw TransactionResolutionException(it.ref.txhash)
}
return LedgerTransaction.createForConclaveVerify(
inputs = conclaveLedgerTxModel.inputStates.toList(),
outputs = wireTransaction.outputs,
commands = wireTransaction.commands.map {
CommandWithParties(it.signers, emptyList(), it.value)
},
attachments = conclaveLedgerTxModel.attachments.toList(),
id = wireTransaction.id,
notary = wireTransaction.notary,
timeWindow = wireTransaction.timeWindow,
privacySalt = wireTransaction.privacySalt,
networkParameters = conclaveLedgerTxModel.networkParameters,
references = conclaveLedgerTxModel.references.toList(),
componentGroups = wireTransaction.componentGroups,
serializedInputs = serializedResolvedInputs,
serializedReferences = serializedResolvedReferences,
digestService = wireTransaction.digestService
)
}
@JvmStatic
fun resolveStateRefBinaryComponent(stateRef: StateRef, dependencyMap: Map<SecureHash, SignedTransaction>)
: SerializedStateAndRef? {
val wireTransaction = dependencyMap[stateRef.txhash]?.tx
?: throw TransactionResolutionException(stateRef.txhash)
val resolvedState = wireTransaction.componentGroups
.firstOrNull { it.groupIndex == ComponentGroupEnum.OUTPUTS_GROUP.ordinal }
?.components
?.get(stateRef.index) as SerializedBytes<TransactionState<ContractState>>?
return resolvedState?.let { SerializedStateAndRef(it, stateRef) }
}
}
}