Skip to content

Commit

Permalink
Added verifySignaturesExcept which takes in a colleciton of PublicKeys
Browse files Browse the repository at this point in the history
  • Loading branch information
shamsasari committed Nov 7, 2017
1 parent deaba28 commit e6feca2
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<TransactionSignature>

/** Specifies all the public keys that require signatures for the transaction to be valid */
Expand All @@ -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.
Expand All @@ -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<PublicKey>) {
checkSignaturesAreValid()

val needed = getMissingSigners() - allowedToBeMissing
Expand All @@ -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.
Expand All @@ -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()
}
}
2 changes: 2 additions & 0 deletions docs/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit e6feca2

Please sign in to comment.