From e6feca2f0374c56434953e21daa02f14a94855dc Mon Sep 17 00:00:00 2001 From: Shams Asari Date: Tue, 7 Nov 2017 09:33:19 +0000 Subject: [PATCH] Added verifySignaturesExcept which takes in a colleciton of PublicKeys --- .../corda/core/flows/CollectSignaturesFlow.kt | 4 +-- .../transactions/TransactionWithSignatures.kt | 30 ++++++++++++++++--- docs/source/changelog.rst | 2 ++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/core/src/main/kotlin/net/corda/core/flows/CollectSignaturesFlow.kt b/core/src/main/kotlin/net/corda/core/flows/CollectSignaturesFlow.kt index 8dfe4a69ff..3424afa84a 100644 --- a/core/src/main/kotlin/net/corda/core/flows/CollectSignaturesFlow.kt +++ b/core/src/main/kotlin/net/corda/core/flows/CollectSignaturesFlow.kt @@ -91,7 +91,7 @@ class CollectSignaturesFlow @JvmOverloads constructor(val partiallySignedTx: Sig } // The signatures must be valid and the transaction must be valid. - partiallySignedTx.verifySignaturesExcept(*notSigned.toTypedArray()) + partiallySignedTx.verifySignaturesExcept(notSigned) partiallySignedTx.tx.toLedgerTransaction(serviceHub).verify() // Determine who still needs to sign. @@ -251,7 +251,7 @@ abstract class SignTransactionFlow(val otherSideSession: FlowSession, val signed = stx.sigs.map { it.by } val allSigners = stx.tx.requiredSigningKeys val notSigned = allSigners - signed - stx.verifySignaturesExcept(*notSigned.toTypedArray()) + stx.verifySignaturesExcept(notSigned) } /** diff --git a/core/src/main/kotlin/net/corda/core/transactions/TransactionWithSignatures.kt b/core/src/main/kotlin/net/corda/core/transactions/TransactionWithSignatures.kt index 6835e39686..8999a62056 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/TransactionWithSignatures.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/TransactionWithSignatures.kt @@ -9,10 +9,16 @@ import net.corda.core.utilities.toNonEmptySet import java.security.InvalidKeyException import java.security.PublicKey import java.security.SignatureException +import java.util.* /** An interface for transactions containing signatures, with logic for signature verification */ @DoNotImplement interface TransactionWithSignatures : NamedByHash { + /** + * List of signatures on this transaction. + * @see checkSignaturesAreValid + * @see verifyRequiredSignatures + */ val sigs: List /** Specifies all the public keys that require signatures for the transaction to be valid */ @@ -26,7 +32,7 @@ interface TransactionWithSignatures : NamedByHash { * @throws SignaturesMissingException if any signatures should have been present but were not. */ @Throws(SignatureException::class) - fun verifyRequiredSignatures() = verifySignaturesExcept() + fun verifyRequiredSignatures() = verifySignaturesExcept(emptySet()) /** * Verifies the signatures on this transaction and throws if any are missing which aren't passed as parameters. @@ -42,6 +48,23 @@ interface TransactionWithSignatures : NamedByHash { */ @Throws(SignatureException::class) fun verifySignaturesExcept(vararg allowedToBeMissing: PublicKey) { + verifySignaturesExcept(Arrays.asList(*allowedToBeMissing)) + } + + /** + * Verifies the signatures on this transaction and throws if any are missing which aren't passed as parameters. + * In this context, "verifying" means checking they are valid signatures and that their public keys are in + * the [requiredSigningKeys] set. + * + * Normally you would not provide any keys to this function, but if you're in the process of building a partial + * transaction and you want to access the contents before you've signed it, you can specify your own keys here + * to bypass that check. + * + * @throws SignatureException if any signatures are invalid or unrecognised. + * @throws SignaturesMissingException if any signatures should have been present but were not. + */ + @Throws(SignatureException::class) + fun verifySignaturesExcept(allowedToBeMissing: Collection) { checkSignaturesAreValid() val needed = getMissingSigners() - allowedToBeMissing @@ -53,7 +76,7 @@ interface TransactionWithSignatures : NamedByHash { * Mathematically validates the signatures that are present on this transaction. This does not imply that * the signatures are by the right keys, or that there are sufficient signatures, just that they aren't * corrupt. If you use this function directly you'll need to do the other checks yourself. Probably you - * want [verifySignatures] instead. + * want [verifyRequiredSignatures] instead. * * @throws InvalidKeyException if the key on a signature is invalid. * @throws SignatureException if a signature fails to verify. @@ -80,7 +103,6 @@ interface TransactionWithSignatures : NamedByHash { val sigKeys = sigs.map { it.by }.toSet() // TODO Problem is that we can get single PublicKey wrapped as CompositeKey in allowedToBeMissing/mustSign // equals on CompositeKey won't catch this case (do we want to single PublicKey be equal to the same key wrapped in CompositeKey with threshold 1?) - val missing = requiredSigningKeys.filter { !it.isFulfilledBy(sigKeys) }.toSet() - return missing + return requiredSigningKeys.filter { !it.isFulfilledBy(sigKeys) }.toSet() } } \ No newline at end of file diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index dae68708fe..c08ba3e844 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -75,6 +75,8 @@ UNRELEASED * Moved ``NodeInfoSchema`` to internal package as the node info's database schema is not part of the public API. This is needed to allow new ``node_info_hash`` column to be added for the network map redesign work. +* Added an overload of ``TransactionWithSignatures.verifySignaturesExcept`` which takes in a collection of ``PublicKey``s. + .. _changelog_v1: Release 1.0