Skip to content

Commit 5703c44

Browse files
authored
R3SOL-1446 signing verifying extraction (#6398)
restructured C5 to share verification and signing services with corda-dlt --------- Co-authored-by: PranuR3 <[email protected]> Co-authored-by: Dan Newton <[email protected]>
1 parent ed8b0e1 commit 5703c44

File tree

14 files changed

+287
-111
lines changed

14 files changed

+287
-111
lines changed

components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/factory/impl/UtxoSignedTransactionFactoryOsgiImpl.kt

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import net.corda.ledger.lib.utxo.flow.impl.transaction.factory.UtxoSignedTransac
1111
import net.corda.ledger.lib.utxo.flow.impl.transaction.factory.impl.UtxoSignedTransactionFactoryImpl
1212
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal
1313
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.UtxoLedgerTransactionVerificationService
14+
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.UtxoSignedTransactionSignatureVerificationService
1415
import net.corda.ledger.utxo.flow.impl.groupparameters.verifier.SignedGroupParametersVerifier
1516
import net.corda.ledger.utxo.flow.impl.persistence.UtxoLedgerGroupParametersPersistenceService
1617
import net.corda.libs.json.validator.JsonValidator
@@ -56,6 +57,8 @@ class UtxoSignedTransactionFactoryOsgiImpl(
5657
utxoLedgerTransactionVerificationService: UtxoLedgerTransactionVerificationService,
5758
@Reference(service = UtxoLedgerGroupParametersPersistenceService::class)
5859
utxoLedgerGroupParametersPersistenceService: UtxoLedgerGroupParametersPersistenceService,
60+
@Reference(service = UtxoSignedTransactionSignatureVerificationService::class)
61+
utxoSignedTransactionSignatureVerificationService: UtxoSignedTransactionSignatureVerificationService,
5962
@Reference(service = GroupParametersLookupInternal::class)
6063
groupParametersLookup: GroupParametersLookupInternal,
6164
@Reference(service = SignedGroupParametersVerifier::class)
@@ -84,7 +87,8 @@ class UtxoSignedTransactionFactoryOsgiImpl(
8487
mapOf<String, Any>(
8588
TransactionMetadataImpl.MEMBERSHIP_GROUP_PARAMETERS_HASH_KEY to signedGroupParameters.hash.toString()
8689
)
87-
}
90+
},
91+
utxoSignedTransactionSignatureVerificationService
8892
)
8993
)
9094
}

components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/serializer/amqp/UtxoSignedTransactionSerializer.kt

+6-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import net.corda.ledger.lib.utxo.flow.impl.transaction.UtxoSignedTransactionImpl
66
import net.corda.ledger.lib.utxo.flow.impl.transaction.UtxoSignedTransactionInternal
77
import net.corda.ledger.lib.utxo.flow.impl.transaction.factory.UtxoLedgerTransactionFactory
88
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal
9+
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.UtxoSignedTransactionSignatureVerificationService
910
import net.corda.sandbox.type.SandboxConstants.CORDA_UNINJECTABLE_SERVICE
1011
import net.corda.sandbox.type.UsedByFlow
1112
import net.corda.serialization.BaseProxySerializer
@@ -31,7 +32,9 @@ class UtxoSignedTransactionSerializer @Activate constructor(
3132
@Reference(service = UtxoLedgerTransactionFactory::class)
3233
private val utxoLedgerTransactionFactory: UtxoLedgerTransactionFactory,
3334
@Reference(service = NotarySignatureVerificationServiceInternal::class)
34-
private val notarySignatureVerificationService: NotarySignatureVerificationServiceInternal
35+
private val notarySignatureVerificationService: NotarySignatureVerificationServiceInternal,
36+
@Reference(service = UtxoSignedTransactionSignatureVerificationService::class)
37+
private val utxoSignedTransactionSignatureVerificationService: UtxoSignedTransactionSignatureVerificationService,
3538
) : BaseProxySerializer<UtxoSignedTransactionInternal, UtxoSignedTransactionProxy>(), UsedByFlow {
3639
private companion object {
3740
private const val VERSION_1 = 1
@@ -64,7 +67,8 @@ class UtxoSignedTransactionSerializer @Activate constructor(
6467
notarySignatureVerificationService,
6568
utxoLedgerTransactionFactory,
6669
proxy.wireTransaction,
67-
proxy.signatures.toSet()
70+
proxy.signatures.toSet(),
71+
utxoSignedTransactionSignatureVerificationService
6872
)
6973
else ->
7074
throw CordaRuntimeException("Unable to create UtxoSignedTransaction with Version='${proxy.version}'")

components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/serializer/kryo/UtxoSignedTransactionKryoSerializer.kt

+6-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import net.corda.ledger.lib.utxo.flow.impl.transaction.UtxoSignedTransactionImpl
66
import net.corda.ledger.lib.utxo.flow.impl.transaction.UtxoSignedTransactionInternal
77
import net.corda.ledger.lib.utxo.flow.impl.transaction.factory.UtxoLedgerTransactionFactory
88
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal
9+
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.UtxoSignedTransactionSignatureVerificationService
910
import net.corda.sandbox.type.SandboxConstants.CORDA_UNINJECTABLE_SERVICE
1011
import net.corda.sandbox.type.UsedByFlow
1112
import net.corda.serialization.checkpoint.CheckpointInput
@@ -31,7 +32,9 @@ class UtxoSignedTransactionKryoSerializer @Activate constructor(
3132
@Reference(service = UtxoLedgerTransactionFactory::class)
3233
private val utxoLedgerTransactionFactory: UtxoLedgerTransactionFactory,
3334
@Reference(service = NotarySignatureVerificationServiceInternal::class)
34-
private val notarySignatureVerificationService: NotarySignatureVerificationServiceInternal
35+
private val notarySignatureVerificationService: NotarySignatureVerificationServiceInternal,
36+
@Reference(service = UtxoSignedTransactionSignatureVerificationService::class)
37+
private val utxoSignedTransactionSignatureVerificationService: UtxoSignedTransactionSignatureVerificationService
3538
) : CheckpointInternalCustomSerializer<UtxoSignedTransactionInternal>, UsedByFlow {
3639
override val type: Class<UtxoSignedTransactionInternal> get() = UtxoSignedTransactionInternal::class.java
3740

@@ -51,7 +54,8 @@ class UtxoSignedTransactionKryoSerializer @Activate constructor(
5154
notarySignatureVerificationService,
5255
utxoLedgerTransactionFactory,
5356
wireTransaction,
54-
signatures.toSet()
57+
signatures.toSet(),
58+
utxoSignedTransactionSignatureVerificationService
5559
)
5660
}
5761
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package net.corda.ledger.utxo.flow.impl.transaction.verifier
2+
3+
import net.corda.ledger.common.flow.transaction.TransactionSignatureServiceInternal
4+
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal
5+
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.UtxoSignedTransactionSignatureVerificationService
6+
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.UtxoSignedTransactionSignatureVerificationServiceImpl
7+
import net.corda.sandbox.type.UsedByFlow
8+
import net.corda.v5.serialization.SingletonSerializeAsToken
9+
import org.osgi.service.component.annotations.Activate
10+
import org.osgi.service.component.annotations.Component
11+
import org.osgi.service.component.annotations.Reference
12+
import org.osgi.service.component.annotations.ServiceScope.PROTOTYPE
13+
14+
@Component(service = [UtxoSignedTransactionSignatureVerificationService::class, UsedByFlow::class], scope = PROTOTYPE)
15+
@Suppress("unused")
16+
class UtxoSignedTransactionSignatureVerificationServiceOsgiImpl private constructor(
17+
delegate: UtxoSignedTransactionSignatureVerificationService
18+
) : UtxoSignedTransactionSignatureVerificationService by delegate, UsedByFlow, SingletonSerializeAsToken {
19+
20+
@Activate
21+
@Suppress("unused")
22+
constructor(
23+
@Reference(service = NotarySignatureVerificationServiceInternal::class)
24+
notarySignatureVerificationService: NotarySignatureVerificationServiceInternal,
25+
@Reference(service = TransactionSignatureServiceInternal::class)
26+
transactionSignatureServiceInternal: TransactionSignatureServiceInternal
27+
) : this(
28+
UtxoSignedTransactionSignatureVerificationServiceImpl(notarySignatureVerificationService, transactionSignatureServiceInternal)
29+
)
30+
}

components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/persistence/UtxoLedgerPersistenceServiceImplTest.kt

+5-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import net.corda.ledger.lib.utxo.flow.impl.transaction.filtered.UtxoFilteredTran
2222
import net.corda.ledger.lib.utxo.flow.impl.transaction.filtered.factory.UtxoFilteredTransactionFactory
2323
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal
2424
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.UtxoSignedLedgerTransactionImpl
25+
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.UtxoSignedTransactionSignatureVerificationService
2526
import net.corda.ledger.utxo.data.transaction.SignedLedgerTransactionContainer
2627
import net.corda.ledger.utxo.data.transaction.UtxoComponentGroup
2728
import net.corda.ledger.utxo.data.transaction.UtxoFilteredTransactionAndSignaturesImpl
@@ -103,6 +104,8 @@ class UtxoLedgerPersistenceServiceImplTest {
103104
private val stateAndRefCache = mock<StateAndRefCache>()
104105
private val flowCheckpointService = mock<FlowCheckpointService>()
105106
private val flowCheckpoint = mock<FlowCheckpoint>()
107+
private val signedTransactionSignatureVerificationService =
108+
mock<UtxoSignedTransactionSignatureVerificationService>()
106109

107110
private val notaryServiceKey = mock<CompositeKey>()
108111
private val publicKeyNotaryVNode1 = mock<PublicKey>().also { whenever(it.encoded).thenReturn(byteArrayOf(0x01)) }
@@ -259,7 +262,8 @@ class UtxoLedgerPersistenceServiceImplTest {
259262
notarySignatureVerificationService,
260263
mock<UtxoLedgerTransactionFactory>(),
261264
wireTransaction,
262-
signatures
265+
signatures,
266+
signedTransactionSignatureVerificationService
263267
)
264268
val testId = parseSecureHash("SHA256:1234567890123456")
265269

libs/ledger-lib-utxo-flow/src/main/kotlin/net/corda/ledger/lib/utxo/flow/impl/transaction/UtxoSignedTransactionImpl.kt

+12-95
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
package net.corda.ledger.lib.utxo.flow.impl.transaction
22

33
import net.corda.ledger.common.data.transaction.WireTransaction
4-
import net.corda.ledger.common.flow.transaction.TransactionMissingSignaturesException
54
import net.corda.ledger.common.flow.transaction.TransactionSignatureServiceInternal
65
import net.corda.ledger.lib.utxo.flow.impl.transaction.factory.UtxoLedgerTransactionFactory
76
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal
7+
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.UtxoSignedTransactionSignatureVerificationService
88
import net.corda.ledger.utxo.data.transaction.WrappedUtxoWireTransaction
99
import net.corda.ledger.utxo.data.transaction.verifier.verifyMetadata
1010
import net.corda.v5.application.crypto.DigitalSignatureAndMetadata
1111
import net.corda.v5.application.serialization.SerializationService
1212
import net.corda.v5.base.annotations.Suspendable
1313
import net.corda.v5.base.types.MemberX500Name
14-
import net.corda.v5.crypto.KeyUtils
1514
import net.corda.v5.crypto.SecureHash
1615
import net.corda.v5.ledger.common.transaction.TransactionMetadata
1716
import net.corda.v5.ledger.common.transaction.TransactionNoAvailableKeysException
18-
import net.corda.v5.ledger.common.transaction.TransactionSignatureException
1917
import net.corda.v5.ledger.utxo.Command
2018
import net.corda.v5.ledger.utxo.StateAndRef
2119
import net.corda.v5.ledger.utxo.StateRef
@@ -31,12 +29,10 @@ data class UtxoSignedTransactionImpl(
3129
private val notarySignatureVerificationService: NotarySignatureVerificationServiceInternal,
3230
private val utxoLedgerTransactionFactory: UtxoLedgerTransactionFactory,
3331
override val wireTransaction: WireTransaction,
34-
private val signatures: Set<DigitalSignatureAndMetadata>
32+
private val signatures: Set<DigitalSignatureAndMetadata>,
33+
private val utxoSignedTransactionSignatureVerificationService: UtxoSignedTransactionSignatureVerificationService
3534
) : UtxoSignedTransactionInternal {
3635

37-
private val keyIdToSignatories: MutableMap<String, Map<SecureHash, PublicKey>> = mutableMapOf()
38-
private val keyIdToNotaryKeys: MutableMap<String, Map<SecureHash, PublicKey>> = mutableMapOf()
39-
4036
init {
4137
require(signatures.isNotEmpty()) { "Tried to instantiate a ${javaClass.simpleName} without any signatures." }
4238
verifyMetadata(wireTransaction.metadata)
@@ -95,7 +91,8 @@ data class UtxoSignedTransactionImpl(
9591
notarySignatureVerificationService,
9692
utxoLedgerTransactionFactory,
9793
wireTransaction,
98-
signatures + signature
94+
signatures + signature,
95+
utxoSignedTransactionSignatureVerificationService
9996
)
10097

10198
@Suspendable
@@ -112,113 +109,33 @@ data class UtxoSignedTransactionImpl(
112109
notarySignatureVerificationService,
113110
utxoLedgerTransactionFactory,
114111
wireTransaction,
115-
signatures + newSignatures
112+
signatures + newSignatures,
113+
utxoSignedTransactionSignatureVerificationService
116114
),
117115
newSignatures
118116
)
119117
}
120118

121-
private fun getSignatoryKeyFromKeyId(keyId: SecureHash): PublicKey? {
122-
val keyIdToPublicKey = keyIdToSignatories.getOrPut(keyId.algorithm) {
123-
// Prepare keyIds for all public keys related to signatories for the relevant algorithm
124-
signatories.flatMap { signatory ->
125-
notarySignatureVerificationService.getKeyOrLeafKeys(signatory).map {
126-
transactionSignatureServiceInternal.getIdOfPublicKey(
127-
it, keyId.algorithm
128-
) to it
129-
}
130-
}.toMap()
131-
}
132-
return keyIdToPublicKey[keyId]
133-
}
134-
135119
// Notary/unknown signatures are ignored.
136120
override fun getMissingSignatories(): Set<PublicKey> {
137-
return getMissingSignatories(getPublicKeysToSignatorySignatures())
121+
return utxoSignedTransactionSignatureVerificationService.getMissingSignatories(this)
138122
}
139123

140124
// Notary/unknown signatures are ignored
141125
override fun verifySignatorySignatures() {
142-
val publicKeysToSignatures =
143-
getPublicKeysToSignatorySignatures()
144-
145-
val missingSignatories = getMissingSignatories(publicKeysToSignatures)
146-
if (missingSignatories.isNotEmpty()) {
147-
throw TransactionMissingSignaturesException(
148-
id,
149-
missingSignatories,
150-
"Transaction $id is missing signatures for signatories (encoded) ${
151-
missingSignatories.map { it.encoded }
152-
}"
153-
)
154-
}
155-
publicKeysToSignatures.forEach { (publicKey, signature) ->
156-
try {
157-
transactionSignatureServiceInternal.verifySignature(this, signature, publicKey)
158-
} catch (e: Exception) {
159-
throw TransactionSignatureException(
160-
id,
161-
"Failed to verify signature of $signature from $publicKey for transaction $id. Message: ${e.message}",
162-
e
163-
)
164-
}
165-
}
166-
}
167-
168-
private fun getMissingSignatories(publicKeysToSignatures: Map<PublicKey, DigitalSignatureAndMetadata>): Set<PublicKey> {
169-
val publicKeysWithSignatures = publicKeysToSignatures.keys.toHashSet()
170-
171-
// TODO CORE-12207 isKeyFulfilledBy is not the most efficient
172-
// isKeyFulfilledBy() helps to make this working with CompositeKeys.
173-
return signatories
174-
.filterNot { KeyUtils.isKeyFulfilledBy(it, publicKeysWithSignatures) }
175-
.toSet()
176-
}
177-
178-
private fun getPublicKeysToSignatorySignatures(): Map<PublicKey, DigitalSignatureAndMetadata> {
179-
return signatures.mapNotNull { // We do not care about non-notary/non-signatory keys
180-
(getSignatoryKeyFromKeyId(it.by) ?: return@mapNotNull null) to it
181-
}.toMap()
126+
utxoSignedTransactionSignatureVerificationService.verifySignatorySignatures(this)
182127
}
183128

184129
override fun verifyAttachedNotarySignature() {
185-
notarySignatureVerificationService.verifyNotarySignatures(this, notaryKey, signatures.toList(), keyIdToNotaryKeys)
130+
utxoSignedTransactionSignatureVerificationService.verifyAttachedNotarySignature(this)
186131
}
187132

188133
override fun verifyNotarySignature(signature: DigitalSignatureAndMetadata) {
189-
val publicKey = notarySignatureVerificationService.getNotaryPublicKeyByKeyId(signature.by, notaryKey, keyIdToNotaryKeys)
190-
?: throw TransactionSignatureException(
191-
id,
192-
"Notary signature has not been created by the notary for this transaction. " +
193-
"Notary public key: $notaryKey " +
194-
"Notary signature key Id: ${signature.by}",
195-
null
196-
)
197-
198-
try {
199-
transactionSignatureServiceInternal.verifySignature(this, signature, publicKey)
200-
} catch (e: Exception) {
201-
throw TransactionSignatureException(
202-
id,
203-
"Failed to verify notary signature of ${signature.signature} for transaction $id. Message: ${e.message}",
204-
e
205-
)
206-
}
134+
utxoSignedTransactionSignatureVerificationService.verifyNotarySignature(this, signature)
207135
}
208136

209137
override fun verifySignatorySignature(signature: DigitalSignatureAndMetadata) {
210-
val publicKey = getSignatoryKeyFromKeyId(signature.by)
211-
?: return // We do not care about non-notary/non-signatory signatures.
212-
213-
try {
214-
transactionSignatureServiceInternal.verifySignature(this, signature, publicKey)
215-
} catch (e: Exception) {
216-
throw TransactionSignatureException(
217-
id,
218-
"Failed to verify signature of ${signature.signature} for transaction $id. Message: ${e.message}",
219-
e
220-
)
221-
}
138+
utxoSignedTransactionSignatureVerificationService.verifySignatorySignature(this, signature)
222139
}
223140

224141
@Suspendable

libs/ledger-lib-utxo-flow/src/main/kotlin/net/corda/ledger/lib/utxo/flow/impl/transaction/factory/impl/UtxoSignedTransactionFactoryImpl.kt

+7-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import net.corda.ledger.lib.utxo.flow.impl.transaction.factory.UtxoLedgerTransac
1313
import net.corda.ledger.lib.utxo.flow.impl.transaction.factory.UtxoSignedTransactionFactory
1414
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal
1515
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.UtxoLedgerTransactionVerificationService
16+
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.UtxoSignedTransactionSignatureVerificationService
1617
import net.corda.ledger.utxo.data.transaction.UtxoComponentGroup
1718
import net.corda.ledger.utxo.data.transaction.UtxoLedgerTransactionImpl
1819
import net.corda.ledger.utxo.data.transaction.UtxoOutputInfoComponent
@@ -42,7 +43,8 @@ class UtxoSignedTransactionFactoryImpl(
4243
private val notarySignatureVerificationService: NotarySignatureVerificationServiceInternal,
4344
private val privacySaltProviderService: PrivacySaltProviderService,
4445
private val getEvolvableTag: (klass: Class<*>) -> String,
45-
private val getExtraMetadata: () -> Map<String, Any>
46+
private val getExtraMetadata: () -> Map<String, Any>,
47+
private val utxoSignedTransactionSignatureVerificationService: UtxoSignedTransactionSignatureVerificationService
4648
) : UtxoSignedTransactionFactory {
4749

4850
@Suspendable
@@ -74,7 +76,8 @@ class UtxoSignedTransactionFactoryImpl(
7476
notarySignatureVerificationService,
7577
utxoLedgerTransactionFactory,
7678
wireTransaction,
77-
signaturesWithMetadata.toSet()
79+
signaturesWithMetadata.toSet(),
80+
utxoSignedTransactionSignatureVerificationService
7881
)
7982
}
8083

@@ -87,7 +90,8 @@ class UtxoSignedTransactionFactoryImpl(
8790
notarySignatureVerificationService,
8891
utxoLedgerTransactionFactory,
8992
wireTransaction,
90-
signaturesWithMetaData.toSet()
93+
signaturesWithMetaData.toSet(),
94+
utxoSignedTransactionSignatureVerificationService
9195
)
9296

9397
@Suspendable
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package net.corda.ledger.lib.utxo.flow.impl.transaction.verifier
2+
3+
import net.corda.v5.application.crypto.DigitalSignatureAndMetadata
4+
import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction
5+
import java.security.PublicKey
6+
7+
interface UtxoSignedTransactionSignatureVerificationService {
8+
fun getMissingSignatories(transaction: UtxoSignedTransaction): Set<PublicKey>
9+
fun verifySignatorySignatures(transaction: UtxoSignedTransaction)
10+
fun verifyAttachedNotarySignature(transaction: UtxoSignedTransaction)
11+
fun verifyNotarySignature(transaction: UtxoSignedTransaction, signature: DigitalSignatureAndMetadata)
12+
fun verifySignatorySignature(transaction: UtxoSignedTransaction, signature: DigitalSignatureAndMetadata)
13+
}

0 commit comments

Comments
 (0)