1
1
package net.corda.ledger.lib.utxo.flow.impl.transaction
2
2
3
3
import net.corda.ledger.common.data.transaction.WireTransaction
4
- import net.corda.ledger.common.flow.transaction.TransactionMissingSignaturesException
5
4
import net.corda.ledger.common.flow.transaction.TransactionSignatureServiceInternal
6
5
import net.corda.ledger.lib.utxo.flow.impl.transaction.factory.UtxoLedgerTransactionFactory
7
6
import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal
7
+ import net.corda.ledger.lib.utxo.flow.impl.transaction.verifier.UtxoSignedTransactionSignatureVerificationService
8
8
import net.corda.ledger.utxo.data.transaction.WrappedUtxoWireTransaction
9
9
import net.corda.ledger.utxo.data.transaction.verifier.verifyMetadata
10
10
import net.corda.v5.application.crypto.DigitalSignatureAndMetadata
11
11
import net.corda.v5.application.serialization.SerializationService
12
12
import net.corda.v5.base.annotations.Suspendable
13
13
import net.corda.v5.base.types.MemberX500Name
14
- import net.corda.v5.crypto.KeyUtils
15
14
import net.corda.v5.crypto.SecureHash
16
15
import net.corda.v5.ledger.common.transaction.TransactionMetadata
17
16
import net.corda.v5.ledger.common.transaction.TransactionNoAvailableKeysException
18
- import net.corda.v5.ledger.common.transaction.TransactionSignatureException
19
17
import net.corda.v5.ledger.utxo.Command
20
18
import net.corda.v5.ledger.utxo.StateAndRef
21
19
import net.corda.v5.ledger.utxo.StateRef
@@ -31,12 +29,10 @@ data class UtxoSignedTransactionImpl(
31
29
private val notarySignatureVerificationService : NotarySignatureVerificationServiceInternal ,
32
30
private val utxoLedgerTransactionFactory : UtxoLedgerTransactionFactory ,
33
31
override val wireTransaction : WireTransaction ,
34
- private val signatures : Set <DigitalSignatureAndMetadata >
32
+ private val signatures : Set <DigitalSignatureAndMetadata >,
33
+ private val utxoSignedTransactionSignatureVerificationService : UtxoSignedTransactionSignatureVerificationService
35
34
) : UtxoSignedTransactionInternal {
36
35
37
- private val keyIdToSignatories: MutableMap <String , Map <SecureHash , PublicKey >> = mutableMapOf ()
38
- private val keyIdToNotaryKeys: MutableMap <String , Map <SecureHash , PublicKey >> = mutableMapOf ()
39
-
40
36
init {
41
37
require(signatures.isNotEmpty()) { " Tried to instantiate a ${javaClass.simpleName} without any signatures." }
42
38
verifyMetadata(wireTransaction.metadata)
@@ -95,7 +91,8 @@ data class UtxoSignedTransactionImpl(
95
91
notarySignatureVerificationService,
96
92
utxoLedgerTransactionFactory,
97
93
wireTransaction,
98
- signatures + signature
94
+ signatures + signature,
95
+ utxoSignedTransactionSignatureVerificationService
99
96
)
100
97
101
98
@Suspendable
@@ -112,113 +109,33 @@ data class UtxoSignedTransactionImpl(
112
109
notarySignatureVerificationService,
113
110
utxoLedgerTransactionFactory,
114
111
wireTransaction,
115
- signatures + newSignatures
112
+ signatures + newSignatures,
113
+ utxoSignedTransactionSignatureVerificationService
116
114
),
117
115
newSignatures
118
116
)
119
117
}
120
118
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
-
135
119
// Notary/unknown signatures are ignored.
136
120
override fun getMissingSignatories (): Set <PublicKey > {
137
- return getMissingSignatories(getPublicKeysToSignatorySignatures() )
121
+ return utxoSignedTransactionSignatureVerificationService. getMissingSignatories(this )
138
122
}
139
123
140
124
// Notary/unknown signatures are ignored
141
125
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 )
182
127
}
183
128
184
129
override fun verifyAttachedNotarySignature () {
185
- notarySignatureVerificationService.verifyNotarySignatures (this , notaryKey, signatures.toList(), keyIdToNotaryKeys )
130
+ utxoSignedTransactionSignatureVerificationService.verifyAttachedNotarySignature (this )
186
131
}
187
132
188
133
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)
207
135
}
208
136
209
137
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)
222
139
}
223
140
224
141
@Suspendable
0 commit comments