Change CashIssueFlow to use anonymous identity

* Add functions for:
    * Retrieving nodes via their legal identity
    * Filtering a set of public keys down to those the node has corresponding private keys for
* Modify contract upgrade flows to handle identifying participants after an anomymisation step
* Correct terminology: "party who" -> "party which"
* Modify CashIssueFlow and CashPaymentFlow to optionally use an anonymous identity for the recipient.
This commit is contained in:
Ross Nicoll
2017-06-28 13:47:50 +01:00
committed by GitHub
parent e5395fe1b7
commit 1a4965c294
57 changed files with 464 additions and 205 deletions

View File

@ -13,7 +13,10 @@ import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.InitiatingFlow
import net.corda.core.identity.Party
import net.corda.core.node.ServiceHub
import net.corda.core.node.services.Vault
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.unconsumedStates
import net.corda.core.node.services.vault.QueryCriteria
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.unwrap
@ -39,14 +42,15 @@ private fun gatherOurInputs(serviceHub: ServiceHub,
amountRequired: Amount<Issued<Currency>>,
notary: Party?): Pair<List<StateAndRef<Cash.State>>, Long> {
// Collect cash type inputs
val cashStates = serviceHub.vaultService.unconsumedStates<Cash.State>()
val queryCriteria = QueryCriteria.VaultQueryCriteria(Vault.StateStatus.UNCONSUMED, setOf(Cash.State::class.java))
val cashStates = serviceHub.vaultQueryService.queryBy<Cash.State>(queryCriteria).states
// extract our identity for convenience
val ourIdentity = serviceHub.myInfo.legalIdentity
val ourKeys = serviceHub.keyManagementService.keys
// Filter down to our own cash states with right currency and issuer
val suitableCashStates = cashStates.filter {
val state = it.state.data
(state.owner == ourIdentity)
&& (state.amount.token == amountRequired.token)
// TODO: We may want to have the list of our states pre-cached somewhere for performance
(state.owner.owningKey in ourKeys) && (state.amount.token == amountRequired.token)
}
require(!suitableCashStates.isEmpty()) { "Insufficient funds" }
var remaining = amountRequired.quantity
@ -132,9 +136,6 @@ class ForeignExchangeFlow(val tradeId: String,
require(it.inputs.all { it.state.notary == notary }) {
"notary of remote states must be same as for our states"
}
require(it.inputs.all { it.state.data.owner == remoteRequestWithNotary.owner }) {
"The inputs are not owned by the correct counterparty"
}
require(it.inputs.all { it.state.data.amount.token == remoteRequestWithNotary.amount.token }) {
"Inputs not of the correct currency"
}
@ -200,7 +201,7 @@ class ForeignExchangeFlow(val tradeId: String,
// We have already validated their response and trust our own data
// so we can sign. Note the returned SignedTransaction is still not fully signed
// and would not pass full verification yet.
return serviceHub.signInitialTransaction(builder)
return serviceHub.signInitialTransaction(builder, ourSigners.single())
}
// DOCEND 3
}
@ -234,10 +235,11 @@ class ForeignExchangeRemoteFlow(val source: Party) : FlowLogic<Unit>() {
val ourResponse = prepareOurInputsAndOutputs(serviceHub, request)
// Send back our proposed states and await the full transaction to verify
val ourKey = serviceHub.keyManagementService.filterMyKeys(ourResponse.inputs.flatMap { it.state.data.participants }.map { it.owningKey }).single()
val proposedTrade = sendAndReceive<SignedTransaction>(source, ourResponse).unwrap {
val wtx = it.tx
// check all signatures are present except our own and the notary
it.verifySignatures(serviceHub.myInfo.legalIdentity.owningKey, wtx.notary!!.owningKey)
it.verifySignatures(ourKey, wtx.notary!!.owningKey)
// We need to fetch their complete input states and dependencies so that verify can operate
checkDependencies(it)
@ -251,7 +253,7 @@ class ForeignExchangeRemoteFlow(val source: Party) : FlowLogic<Unit>() {
}
// assuming we have completed state and business level validation we can sign the trade
val ourSignature = serviceHub.createSignature(proposedTrade)
val ourSignature = serviceHub.createSignature(proposedTrade, ourKey)
// send the other side our signature.
send(source, ourSignature)