From a3fd54bdb014d4aaaa6490c957015c862122262c Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Mon, 12 Jun 2017 15:49:35 +0100 Subject: [PATCH] Modify generateExit to return full set of signing keys Modify generateExit to return full set of signing keys in preparation for anonymity work meaning that owner and issuer keys are typically not the same. --- .../kotlin/net/corda/core/node/ServiceHub.kt | 2 +- .../net/corda/contracts/asset/Obligation.kt | 4 ++-- .../net/corda/contracts/asset/OnLedgerAsset.kt | 16 +++++++++------- .../contracts/clause/AbstractConserveAmount.kt | 4 ++-- .../main/kotlin/net/corda/flows/CashExitFlow.kt | 4 ++-- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt b/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt index 42733ab4b3..0c0af907f8 100644 --- a/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt +++ b/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt @@ -149,7 +149,7 @@ interface ServiceHub : ServicesForResolution { * @throws IllegalArgumentException is thrown if any keys are unavailable locally. * @return Returns a [SignedTransaction] with the new node signature attached. */ - fun signInitialTransaction(builder: TransactionBuilder, signingPubKeys: List): SignedTransaction { + fun signInitialTransaction(builder: TransactionBuilder, signingPubKeys: Iterable): SignedTransaction { var stx: SignedTransaction? = null for (pubKey in signingPubKeys) { stx = if (stx == null) { diff --git a/finance/src/main/kotlin/net/corda/contracts/asset/Obligation.kt b/finance/src/main/kotlin/net/corda/contracts/asset/Obligation.kt index 97b6dda9fe..62052949a0 100644 --- a/finance/src/main/kotlin/net/corda/contracts/asset/Obligation.kt +++ b/finance/src/main/kotlin/net/corda/contracts/asset/Obligation.kt @@ -455,11 +455,11 @@ class Obligation

: Contract { * @param amountIssued the amount to be exited, represented as a quantity of issued currency. * @param assetStates the asset states to take funds from. No checks are done about ownership of these states, it is * the responsibility of the caller to check that they do not exit funds held by others. - * @return the public key of the assets issuer, who must sign the transaction for it to be valid. + * @return the public keys who must sign the transaction for it to be valid. */ @Suppress("unused") fun generateExit(tx: TransactionBuilder, amountIssued: Amount>>, - assetStates: List>>): PublicKey + assetStates: List>>): Set = OnLedgerAsset.generateExit(tx, amountIssued, assetStates, deriveState = { state, amount, owner -> state.copy(data = state.data.move(amount, owner)) }, generateMoveCommand = { -> Commands.Move() }, diff --git a/finance/src/main/kotlin/net/corda/contracts/asset/OnLedgerAsset.kt b/finance/src/main/kotlin/net/corda/contracts/asset/OnLedgerAsset.kt index 175182d48a..a6d3bd4185 100644 --- a/finance/src/main/kotlin/net/corda/contracts/asset/OnLedgerAsset.kt +++ b/finance/src/main/kotlin/net/corda/contracts/asset/OnLedgerAsset.kt @@ -159,7 +159,7 @@ abstract class OnLedgerAsset> : C * @param amountIssued the amount to be exited, represented as a quantity of issued currency. * @param assetStates the asset states to take funds from. No checks are done about ownership of these states, it is * the responsibility of the caller to check that they do not attempt to exit funds held by others. - * @return the public key of the assets issuer, who must sign the transaction for it to be valid. + * @return the public keys which must sign the transaction for it to be valid. */ @Throws(InsufficientBalanceException::class) @JvmStatic @@ -167,7 +167,7 @@ abstract class OnLedgerAsset> : C assetStates: List>, deriveState: (TransactionState, Amount>, AbstractParty) -> TransactionState, generateMoveCommand: () -> CommandData, - generateExitCommand: (Amount>) -> CommandData): PublicKey { + generateExitCommand: (Amount>) -> CommandData): Set { val owner = assetStates.map { it.state.data.owner }.toSet().singleOrNull() ?: throw InsufficientBalanceException(amountIssued) val currency = amountIssued.token.product val amount = Amount(amountIssued.quantity, currency) @@ -193,9 +193,11 @@ abstract class OnLedgerAsset> : C for (state in gathered) tx.addInputState(state) for (state in outputs) tx.addOutputState(state) - tx.addCommand(generateMoveCommand(), gathered.map { it.state.data.owner.owningKey }) - tx.addCommand(generateExitCommand(amountIssued), gathered.flatMap { it.state.data.exitKeys }) - return amountIssued.token.issuer.party.owningKey + val moveKeys = gathered.map { it.state.data.owner.owningKey } + val exitKeys = gathered.flatMap { it.state.data.exitKeys } + tx.addCommand(generateMoveCommand(), moveKeys) + tx.addCommand(generateExitCommand(amountIssued), exitKeys) + return (moveKeys + exitKeys).toSet() } /** @@ -226,11 +228,11 @@ abstract class OnLedgerAsset> : C * necessarily owned by us. * @param assetStates the asset states to take funds from. No checks are done about ownership of these states, it is * the responsibility of the caller to check that they do not exit funds held by others. - * @return the public key of the assets issuer, who must sign the transaction for it to be valid. + * @return the public keys which must sign the transaction for it to be valid. */ @Throws(InsufficientBalanceException::class) fun generateExit(tx: TransactionBuilder, amountIssued: Amount>, - assetStates: List>): PublicKey { + assetStates: List>): Set { return generateExit( tx, amountIssued, diff --git a/finance/src/main/kotlin/net/corda/contracts/clause/AbstractConserveAmount.kt b/finance/src/main/kotlin/net/corda/contracts/clause/AbstractConserveAmount.kt index c48386cd1e..f2fa484632 100644 --- a/finance/src/main/kotlin/net/corda/contracts/clause/AbstractConserveAmount.kt +++ b/finance/src/main/kotlin/net/corda/contracts/clause/AbstractConserveAmount.kt @@ -26,7 +26,7 @@ abstract class AbstractConserveAmount, C : CommandData, T : * @param amountIssued the amount to be exited, represented as a quantity of issued currency. * @param assetStates the asset states to take funds from. No checks are done about ownership of these states, it is * the responsibility of the caller to check that they do not attempt to exit funds held by others. - * @return the public key of the assets issuer, who must sign the transaction for it to be valid. + * @return the public keys which must sign the transaction for it to be valid. */ @Deprecated("This function will be removed in a future milestone", ReplaceWith("OnLedgerAsset.generateExit()")) @Throws(InsufficientBalanceException::class) @@ -34,7 +34,7 @@ abstract class AbstractConserveAmount, C : CommandData, T : assetStates: List>, deriveState: (TransactionState, Amount>, AbstractParty) -> TransactionState, generateMoveCommand: () -> CommandData, - generateExitCommand: (Amount>) -> CommandData): PublicKey + generateExitCommand: (Amount>) -> CommandData): Set = OnLedgerAsset.generateExit(tx, amountIssued, assetStates, deriveState, generateMoveCommand, generateExitCommand) override fun verify(tx: TransactionForContract, diff --git a/finance/src/main/kotlin/net/corda/flows/CashExitFlow.kt b/finance/src/main/kotlin/net/corda/flows/CashExitFlow.kt index 7ffc67220e..7a9e441668 100644 --- a/finance/src/main/kotlin/net/corda/flows/CashExitFlow.kt +++ b/finance/src/main/kotlin/net/corda/flows/CashExitFlow.kt @@ -36,7 +36,7 @@ class CashExitFlow(val amount: Amount, val issueRef: OpaqueBytes, prog val builder: TransactionBuilder = TransactionType.General.Builder(notary = null as Party?) val issuer = serviceHub.myInfo.legalIdentity.ref(issueRef) val exitStates = serviceHub.vaultService.unconsumedStatesForSpending(amount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference)) - try { + val signers = try { Cash().generateExit( builder, amount.issuedBy(issuer), @@ -62,7 +62,7 @@ class CashExitFlow(val amount: Amount, val issueRef: OpaqueBytes, prog .toSet() // Sign transaction progressTracker.currentStep = SIGNING_TX - val tx = serviceHub.signInitialTransaction(builder) + val tx = serviceHub.signInitialTransaction(builder, signers) // Commit the transaction progressTracker.currentStep = FINALISING_TX