Adding createSignature(filteredTransaction) to serviceHub (#1380)

This commit is contained in:
Konstantinos Chalkias 2017-09-01 10:45:01 +01:00 committed by GitHub
parent 485c2feb83
commit 62c64ace23
8 changed files with 56 additions and 22 deletions

View File

@ -7,6 +7,7 @@ import net.corda.core.crypto.SignatureMetadata
import net.corda.core.crypto.TransactionSignature
import net.corda.core.node.services.*
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.transactions.FilteredTransaction
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import java.security.PublicKey
@ -171,7 +172,7 @@ interface ServiceHub : ServicesForResolution {
/**
* Helper method to construct an initial partially signed transaction from a TransactionBuilder
* using the default identity key contained in the node. The legal Indentity key is used to sign.
* using the default identity key contained in the node. The legal identity key is used to sign.
* @param builder The TransactionBuilder to seal with the node's signature.
* Any existing signatures on the builder will be preserved.
* @return Returns a SignedTransaction with the new node signature attached.
@ -203,7 +204,9 @@ interface ServiceHub : ServicesForResolution {
}
/**
* Helper method to create an additional signature for an existing (partially) [SignedTransaction].
* Helper method to create an additional signature for an existing (partially) [SignedTransaction]. Additional
* [SignatureMetadata], including the
* platform version used during signing and the cryptographic signature scheme use, is added to the signature.
* @param signedTransaction The [SignedTransaction] to which the signature will apply.
* @param publicKey The [PublicKey] matching to a signing [java.security.PrivateKey] hosted in the node.
* If the [PublicKey] is actually a [net.corda.core.crypto.CompositeKey] the first leaf key found locally will be used
@ -214,10 +217,12 @@ interface ServiceHub : ServicesForResolution {
createSignature(signedTransaction, publicKey, SignatureMetadata(myInfo.platformVersion, Crypto.findSignatureScheme(publicKey).schemeNumberID))
/**
* Helper method to create an additional signature for an existing (partially) [SignedTransaction]
* using the default identity signing key of the node. The legal identity key is used to sign.
* Helper method to create a signature for an existing (partially) [SignedTransaction]
* using the default identity signing key of the node. The legal identity key is used to sign. Additional
* [SignatureMetadata], including the
* platform version used during signing and the cryptographic signature scheme use, is added to the signature.
* @param signedTransaction The SignedTransaction to which the signature will apply.
* @return The DigitalSignature.WithKey generated by signing with the internally held identity PrivateKey.
* @return the TransactionSignature generated by signing with the internally held identity PrivateKey.
*/
fun createSignature(signedTransaction: SignedTransaction): TransactionSignature {
return createSignature(signedTransaction, legalIdentityKey)
@ -243,6 +248,36 @@ interface ServiceHub : ServicesForResolution {
*/
fun addSignature(signedTransaction: SignedTransaction): SignedTransaction = addSignature(signedTransaction, legalIdentityKey)
// Helper method to create a signature for a FilteredTransaction.
private fun createSignature(filteredTransaction: FilteredTransaction, publicKey: PublicKey, signatureMetadata: SignatureMetadata): TransactionSignature {
val signableData = SignableData(filteredTransaction.id, signatureMetadata)
return keyManagementService.sign(signableData, publicKey)
}
/**
* Helper method to create a signature for a FilteredTransaction. Additional [SignatureMetadata], including the
* platform version used during signing and the cryptographic signature scheme use, is added to the signature.
* @param filteredTransaction the [FilteredTransaction] to which the signature will apply.
* @param publicKey The [PublicKey] matching to a signing [java.security.PrivateKey] hosted in the node.
* If the [PublicKey] is actually a [net.corda.core.crypto.CompositeKey] the first leaf key found locally will be used
* for signing.
* @return The [TransactionSignature] generated by signing with the internally held [java.security.PrivateKey].
*/
fun createSignature(filteredTransaction: FilteredTransaction, publicKey: PublicKey) =
createSignature(filteredTransaction, publicKey, SignatureMetadata(myInfo.platformVersion, Crypto.findSignatureScheme(publicKey).schemeNumberID))
/**
* Helper method to create a signature for a FilteredTransaction
* using the default identity signing key of the node. The legal identity key is used to sign. Additional
* [SignatureMetadata], including the platform version used during signing and the cryptographic signature scheme use,
* is added to the signature.
* @param filteredTransaction the FilteredTransaction to which the signature will apply.
* @return the [TransactionSignature] generated by signing with the internally held identity [java.security.PrivateKey].
*/
fun createSignature(filteredTransaction: FilteredTransaction): TransactionSignature {
return createSignature(filteredTransaction, legalIdentityKey)
}
/**
* Exposes a JDBC connection (session) object using the currently configured database.
* Applications can use this to execute arbitrary SQL queries (native, direct, prepared, callable)

View File

@ -139,13 +139,13 @@ class FilteredLeaves(
/**
* Class representing merkleized filtered transaction.
* @param rootHash Merkle tree root hash.
* @param id Merkle tree root hash.
* @param filteredLeaves Leaves included in a filtered transaction.
* @param partialMerkleTree Merkle branch needed to verify filteredLeaves.
*/
@CordaSerializable
class FilteredTransaction private constructor(
val rootHash: SecureHash,
val id: SecureHash,
val filteredLeaves: FilteredLeaves,
val partialMerkleTree: PartialMerkleTree
) {
@ -230,13 +230,13 @@ class FilteredTransaction private constructor(
}
/**
* Runs verification of Partial Merkle Branch against [rootHash].
* Runs verification of Partial Merkle Branch against [id].
*/
@Throws(MerkleTreeException::class)
fun verify(): Boolean {
val hashes: List<SecureHash> = filteredLeaves.availableComponentHashes
if (hashes.isEmpty())
throw MerkleTreeException("Transaction without included leaves.")
return partialMerkleTree.verify(rootHash, hashes)
return partialMerkleTree.verify(id, hashes)
}
}

View File

@ -110,6 +110,10 @@ UNRELEASED
* ``SerializationCustomization.addToWhitelist()` now accepts multiple classes via varargs.
* Two functions to easily sign a ``FilteredTransaction`` have been added to ``ServiceHub``:
``createSignature(filteredTransaction: FilteredTransaction, publicKey: PublicKey)`` and
``createSignature(filteredTransaction: FilteredTransaction)`` to sign with the legal identity key.
Milestone 14
------------

View File

@ -45,7 +45,7 @@ In the Oracle example this step takes place in ``RatesFixFlow`` by overriding ``
// Direct accsess to included commands, inputs, outputs, attachments etc.
val cmds: List<Command> = ftx.filteredLeaves.commands
val ins: List<StateRef> = ftx.filteredLeaves.inputs
val timestamp: Timestamp? = ftx.filteredLeaves.timestamp
val timeWindow: TimeWindow? = ftx.filteredLeaves.timeWindow
...
.. literalinclude:: ../../samples/irs-demo/src/main/kotlin/net/corda/irs/api/NodeInterestRates.kt

View File

@ -85,7 +85,7 @@ class BFTNonValidatingNotaryService(override val services: ServiceHubInternal, c
when (response) {
is BFTSMaRt.ClusterResponse.Error -> throw NotaryException(response.error)
is BFTSMaRt.ClusterResponse.Signatures -> {
log.debug("All input states of transaction ${stx.rootHash} have been committed")
log.debug("All input states of transaction ${stx.id} have been committed")
return response.txSignatures
}
}
@ -139,16 +139,13 @@ class BFTNonValidatingNotaryService(override val services: ServiceHubInternal, c
fun verifyAndCommitTx(ftx: FilteredTransaction, callerIdentity: Party): BFTSMaRt.ReplicaResponse {
return try {
val id = ftx.rootHash
val id = ftx.id
val inputs = ftx.filteredLeaves.inputs
validateTimeWindow(ftx.filteredLeaves.timeWindow)
commitInputStates(inputs, id, callerIdentity)
log.debug { "Inputs committed successfully, signing $id" }
val signableData = SignableData(id, SignatureMetadata(services.myInfo.platformVersion, Crypto.findSignatureScheme(services.notaryIdentityKey).schemeNumberID))
val sig = sign(signableData)
BFTSMaRt.ReplicaResponse.Signature(sig)
BFTSMaRt.ReplicaResponse.Signature(sign(ftx))
} catch (e: NotaryException) {
log.debug { "Error processing transaction: ${e.error}" }
BFTSMaRt.ReplicaResponse.Error(e.error)

View File

@ -251,8 +251,8 @@ object BFTSMaRt {
return services.database.transaction { services.keyManagementService.sign(bytes, services.notaryIdentityKey) }
}
protected fun sign(signableData: SignableData): TransactionSignature {
return services.database.transaction { services.keyManagementService.sign(signableData, services.notaryIdentityKey) }
protected fun sign(filteredTransaction: FilteredTransaction): TransactionSignature {
return services.database.transaction { services.createSignature(filteredTransaction, services.notaryIdentityKey) }
}
// TODO:

View File

@ -24,7 +24,7 @@ class NonValidatingNotaryFlow(otherSide: Party, service: TrustedAuthorityNotaryS
when (it) {
is FilteredTransaction -> {
it.verify()
TransactionParts(it.rootHash, it.filteredLeaves.inputs, it.filteredLeaves.timeWindow)
TransactionParts(it.id, it.filteredLeaves.inputs, it.filteredLeaves.timeWindow)
}
is NotaryChangeWireTransaction -> TransactionParts(it.id, it.inputs, null)
else -> {

View File

@ -175,9 +175,7 @@ object NodeInterestRates {
// Note that we will happily sign an invalid transaction, as we are only being presented with a filtered
// version so we can't resolve or check it ourselves. However, that doesn't matter much, as if we sign
// an invalid transaction the signature is worthless.
val signableData = SignableData(ftx.rootHash, SignatureMetadata(services.myInfo.platformVersion, Crypto.findSignatureScheme(signingKey).schemeNumberID))
val signature = services.keyManagementService.sign(signableData, signingKey)
return TransactionSignature(signature.bytes, signingKey, signableData.signatureMetadata)
return services.createSignature(ftx, signingKey)
}
// DOCEND 1