mirror of
https://github.com/corda/corda.git
synced 2024-12-20 21:43:14 +00:00
Extract identity helpers (#1636)
* First compiling version. internal package accessed from finance and irsdemo * Renaming
This commit is contained in:
parent
7cc23f007d
commit
175e53d3d2
@ -7,6 +7,8 @@ import net.corda.core.contracts.StateRef
|
|||||||
import net.corda.core.crypto.TransactionSignature
|
import net.corda.core.crypto.TransactionSignature
|
||||||
import net.corda.core.crypto.isFulfilledBy
|
import net.corda.core.crypto.isFulfilledBy
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
|
import net.corda.core.identity.excludeHostNode
|
||||||
|
import net.corda.core.identity.groupAbstractPartyByWellKnownParty
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.utilities.ProgressTracker
|
import net.corda.core.utilities.ProgressTracker
|
||||||
@ -90,7 +92,7 @@ abstract class AbstractStateReplacementFlow {
|
|||||||
* Initiate sessions with parties we want signatures from.
|
* Initiate sessions with parties we want signatures from.
|
||||||
*/
|
*/
|
||||||
open fun getParticipantSessions(): List<Pair<FlowSession, List<AbstractParty>>> {
|
open fun getParticipantSessions(): List<Pair<FlowSession, List<AbstractParty>>> {
|
||||||
return serviceHub.excludeMe(serviceHub.groupAbstractPartyByWellKnownParty(originalState.state.data.participants)).map { initiateFlow(it.key) to it.value }
|
return excludeHostNode(serviceHub, groupAbstractPartyByWellKnownParty(serviceHub, originalState.state.data.participants)).map { initiateFlow(it.key) to it.value }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suspendable
|
@Suspendable
|
||||||
|
@ -4,6 +4,7 @@ import co.paralleluniverse.fibers.Suspendable
|
|||||||
import net.corda.core.crypto.TransactionSignature
|
import net.corda.core.crypto.TransactionSignature
|
||||||
import net.corda.core.crypto.isFulfilledBy
|
import net.corda.core.crypto.isFulfilledBy
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
|
import net.corda.core.identity.groupPublicKeysByWellKnownParty
|
||||||
import net.corda.core.node.ServiceHub
|
import net.corda.core.node.ServiceHub
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.transactions.WireTransaction
|
import net.corda.core.transactions.WireTransaction
|
||||||
@ -102,7 +103,7 @@ class CollectSignaturesFlow @JvmOverloads constructor (val partiallySignedTx: Si
|
|||||||
// If the unsigned counter-parties list is empty then we don't need to collect any more signatures here.
|
// If the unsigned counter-parties list is empty then we don't need to collect any more signatures here.
|
||||||
if (unsigned.isEmpty()) return partiallySignedTx
|
if (unsigned.isEmpty()) return partiallySignedTx
|
||||||
|
|
||||||
val partyToKeysMap = serviceHub.groupPublicKeysByWellKnownParty(unsigned)
|
val partyToKeysMap = groupPublicKeysByWellKnownParty(serviceHub, unsigned)
|
||||||
// Check that we have a session for all parties. No more, no less.
|
// Check that we have a session for all parties. No more, no less.
|
||||||
require(sessionsToCollectFrom.map { it.counterparty }.toSet() == partyToKeysMap.keys) {
|
require(sessionsToCollectFrom.map { it.counterparty }.toSet() == partyToKeysMap.keys) {
|
||||||
"The Initiator of CollectSignaturesFlow must pass in exactly the sessions required to sign the transaction."
|
"The Initiator of CollectSignaturesFlow must pass in exactly the sessions required to sign the transaction."
|
||||||
@ -241,7 +242,7 @@ abstract class SignTransactionFlow(val otherSideSession: FlowSession,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suspendable private fun checkSignatures(stx: SignedTransaction) {
|
@Suspendable private fun checkSignatures(stx: SignedTransaction) {
|
||||||
val signingWellKnownIdentities = serviceHub.groupPublicKeysByWellKnownParty(stx.sigs.map(TransactionSignature::by))
|
val signingWellKnownIdentities = groupPublicKeysByWellKnownParty(serviceHub, stx.sigs.map(TransactionSignature::by))
|
||||||
require(otherSideSession.counterparty in signingWellKnownIdentities) {
|
require(otherSideSession.counterparty in signingWellKnownIdentities) {
|
||||||
"The Initiator of CollectSignaturesFlow must have signed the transaction. Found ${signingWellKnownIdentities}, expected ${otherSideSession}"
|
"The Initiator of CollectSignaturesFlow must have signed the transaction. Found ${signingWellKnownIdentities}, expected ${otherSideSession}"
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package net.corda.core.flows
|
|||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.core.crypto.isFulfilledBy
|
import net.corda.core.crypto.isFulfilledBy
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
|
import net.corda.core.identity.groupAbstractPartyByWellKnownParty
|
||||||
import net.corda.core.transactions.LedgerTransaction
|
import net.corda.core.transactions.LedgerTransaction
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.utilities.ProgressTracker
|
import net.corda.core.utilities.ProgressTracker
|
||||||
@ -92,7 +93,7 @@ class FinalityFlow(val transaction: SignedTransaction,
|
|||||||
|
|
||||||
private fun getPartiesToSend(ltx: LedgerTransaction): Set<Party> {
|
private fun getPartiesToSend(ltx: LedgerTransaction): Set<Party> {
|
||||||
val participants = ltx.outputStates.flatMap { it.participants } + ltx.inputStates.flatMap { it.participants }
|
val participants = ltx.outputStates.flatMap { it.participants } + ltx.inputStates.flatMap { it.participants }
|
||||||
return serviceHub.groupAbstractPartyByWellKnownParty(participants).keys + extraRecipients
|
return groupAbstractPartyByWellKnownParty(serviceHub, participants).keys + extraRecipients
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun verifyTx(): LedgerTransaction {
|
private fun verifyTx(): LedgerTransaction {
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
@file:JvmName("IdentityUtils")
|
||||||
|
|
||||||
|
package net.corda.core.identity
|
||||||
|
|
||||||
|
import net.corda.core.internal.toMultiMap
|
||||||
|
import net.corda.core.node.ServiceHub
|
||||||
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import java.security.PublicKey
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group each [PublicKey] by the well known party using the [ServiceHub.identityService], in preparation for
|
||||||
|
* creating [FlowSession]s, for example.
|
||||||
|
*
|
||||||
|
* @param publicKeys the [PublicKey]s to group.
|
||||||
|
* @param ignoreUnrecognisedParties if this is false, throw an exception if some of the [PublicKey]s cannot be mapped
|
||||||
|
* to a [Party].
|
||||||
|
* @return a map of well known [Party] to associated [PublicKey]s.
|
||||||
|
*/
|
||||||
|
@Throws(IllegalArgumentException::class)
|
||||||
|
fun groupPublicKeysByWellKnownParty(serviceHub: ServiceHub, publicKeys: Collection<PublicKey>, ignoreUnrecognisedParties: Boolean): Map<Party, List<PublicKey>> =
|
||||||
|
groupAbstractPartyByWellKnownParty(serviceHub, publicKeys.map { AnonymousParty(it) }, ignoreUnrecognisedParties).mapValues { it.value.map { it.owningKey } }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group each [PublicKey] by the well known party using the [ServiceHub.identityService], in preparation for
|
||||||
|
* creating [FlowSession]s, for example. Throw an exception if some of the [PublicKey]s cannot be mapped
|
||||||
|
* to a [Party].
|
||||||
|
*
|
||||||
|
* @param publicKeys the [PublicKey]s to group.
|
||||||
|
* @return a map of well known [Party] to associated [PublicKey]s.
|
||||||
|
*/
|
||||||
|
// Cannot use @JvmOverloads in interface
|
||||||
|
@Throws(IllegalArgumentException::class)
|
||||||
|
fun groupPublicKeysByWellKnownParty(serviceHub: ServiceHub, publicKeys: Collection<PublicKey>): Map<Party, List<PublicKey>> = groupPublicKeysByWellKnownParty(serviceHub, publicKeys, false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group each [AbstractParty] by the well known party using the [ServiceHub.identityService], in preparation for
|
||||||
|
* creating [FlowSession]s, for example.
|
||||||
|
*
|
||||||
|
* @param parties the [AbstractParty]s to group.
|
||||||
|
* @param ignoreUnrecognisedParties if this is false, throw an exception if some of the [AbstractParty]s cannot be mapped
|
||||||
|
* to a [Party].
|
||||||
|
* @return a map of well known [Party] to associated [AbstractParty]s.
|
||||||
|
*/
|
||||||
|
@Throws(IllegalArgumentException::class)
|
||||||
|
fun groupAbstractPartyByWellKnownParty(serviceHub: ServiceHub, parties: Collection<AbstractParty>, ignoreUnrecognisedParties: Boolean): Map<Party, List<AbstractParty>> {
|
||||||
|
val partyToPublicKey: Iterable<Pair<Party, AbstractParty>> = parties.mapNotNull {
|
||||||
|
(serviceHub.identityService.wellKnownPartyFromAnonymous(it) ?: if (ignoreUnrecognisedParties) return@mapNotNull null else throw IllegalArgumentException("Could not find Party for $it")) to it
|
||||||
|
}
|
||||||
|
return partyToPublicKey.toMultiMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group each [AbstractParty] by the well known party using the [ServiceHub.identityService], in preparation for
|
||||||
|
* creating [FlowSession]s, for example. Throw an exception if some of the [AbstractParty]s cannot be mapped
|
||||||
|
* to a [Party].
|
||||||
|
*
|
||||||
|
* @param parties the [AbstractParty]s to group.
|
||||||
|
* @return a map of well known [Party] to associated [AbstractParty]s.
|
||||||
|
*/
|
||||||
|
// Cannot use @JvmOverloads in interface
|
||||||
|
@Throws(IllegalArgumentException::class)
|
||||||
|
fun groupAbstractPartyByWellKnownParty(serviceHub: ServiceHub, parties: Collection<AbstractParty>): Map<Party, List<AbstractParty>> {
|
||||||
|
return groupAbstractPartyByWellKnownParty(serviceHub, parties, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove this node from a map of well known [Party]s.
|
||||||
|
*
|
||||||
|
* @return a new copy of the map, with he well known [Party] for this node removed.
|
||||||
|
*/
|
||||||
|
fun <T> excludeHostNode(serviceHub: ServiceHub, map: Map<Party, T>): Map<Party, T> = map.filterKeys { !serviceHub.myInfo.isLegalIdentity(it) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the [Party] associated with the notary of a [SignedTransaction] from the a map of [Party]s. It is a no-op
|
||||||
|
* if the notary is null.
|
||||||
|
*
|
||||||
|
* @return a new copy of the map, with the well known [Party] for the notary removed.
|
||||||
|
*/
|
||||||
|
fun <T> excludeNotary(map: Map<Party, T>, stx: SignedTransaction): Map<Party, T> = map.filterKeys { it != stx.notary }
|
@ -275,75 +275,4 @@ interface ServiceHub : ServicesForResolution {
|
|||||||
* @return A new [Connection]
|
* @return A new [Connection]
|
||||||
*/
|
*/
|
||||||
fun jdbcSession(): Connection
|
fun jdbcSession(): Connection
|
||||||
|
|
||||||
/**
|
|
||||||
* Group each [PublicKey] by the well known party using the [ServiceHub.identityService], in preparation for
|
|
||||||
* creating [FlowSession]s, for example.
|
|
||||||
*
|
|
||||||
* @param publicKeys the [PublicKey]s to group.
|
|
||||||
* @param ignoreUnrecognisedParties if this is false, throw an exception if some of the [PublicKey]s cannot be mapped
|
|
||||||
* to a [Party].
|
|
||||||
* @return a map of well known [Party] to associated [PublicKey]s.
|
|
||||||
*/
|
|
||||||
@Throws(IllegalArgumentException::class)
|
|
||||||
fun groupPublicKeysByWellKnownParty(publicKeys: Collection<PublicKey>, ignoreUnrecognisedParties: Boolean): Map<Party, List<PublicKey>> =
|
|
||||||
groupAbstractPartyByWellKnownParty(publicKeys.map { AnonymousParty(it) }, ignoreUnrecognisedParties).mapValues { it.value.map { it.owningKey } }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Group each [PublicKey] by the well known party using the [ServiceHub.identityService], in preparation for
|
|
||||||
* creating [FlowSession]s, for example. Throw an exception if some of the [PublicKey]s cannot be mapped
|
|
||||||
* to a [Party].
|
|
||||||
*
|
|
||||||
* @param publicKeys the [PublicKey]s to group.
|
|
||||||
* @return a map of well known [Party] to associated [PublicKey]s.
|
|
||||||
*/
|
|
||||||
// Cannot use @JvmOverloads in interface
|
|
||||||
@Throws(IllegalArgumentException::class)
|
|
||||||
fun groupPublicKeysByWellKnownParty(publicKeys: Collection<PublicKey>): Map<Party, List<PublicKey>> = groupPublicKeysByWellKnownParty(publicKeys, false)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Group each [AbstractParty] by the well known party using the [ServiceHub.identityService], in preparation for
|
|
||||||
* creating [FlowSession]s, for example.
|
|
||||||
*
|
|
||||||
* @param parties the [AbstractParty]s to group.
|
|
||||||
* @param ignoreUnrecognisedParties if this is false, throw an exception if some of the [AbstractParty]s cannot be mapped
|
|
||||||
* to a [Party].
|
|
||||||
* @return a map of well known [Party] to associated [AbstractParty]s.
|
|
||||||
*/
|
|
||||||
@Throws(IllegalArgumentException::class)
|
|
||||||
fun groupAbstractPartyByWellKnownParty(parties: Collection<AbstractParty>, ignoreUnrecognisedParties: Boolean): Map<Party, List<AbstractParty>> {
|
|
||||||
val partyToPublicKey: Iterable<Pair<Party, AbstractParty>> = parties.mapNotNull {
|
|
||||||
(identityService.wellKnownPartyFromAnonymous(it) ?: if (ignoreUnrecognisedParties) return@mapNotNull null else throw IllegalArgumentException("Could not find Party for $it")) to it
|
|
||||||
}
|
|
||||||
return partyToPublicKey.toMultiMap()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Group each [AbstractParty] by the well known party using the [ServiceHub.identityService], in preparation for
|
|
||||||
* creating [FlowSession]s, for example. Throw an exception if some of the [AbstractParty]s cannot be mapped
|
|
||||||
* to a [Party].
|
|
||||||
*
|
|
||||||
* @param parties the [AbstractParty]s to group.
|
|
||||||
* @return a map of well known [Party] to associated [AbstractParty]s.
|
|
||||||
*/
|
|
||||||
// Cannot use @JvmOverloads in interface
|
|
||||||
@Throws(IllegalArgumentException::class)
|
|
||||||
fun groupAbstractPartyByWellKnownParty(parties: Collection<AbstractParty>): Map<Party, List<AbstractParty>> {
|
|
||||||
return groupAbstractPartyByWellKnownParty(parties, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove this node from a map of well known [Party]s.
|
|
||||||
*
|
|
||||||
* @return a new copy of the map, with he well known [Party] for this node removed.
|
|
||||||
*/
|
|
||||||
fun <T> excludeMe(map: Map<Party, T>): Map<Party, T> = map.filterKeys { !myInfo.isLegalIdentity(it) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the [Party] associated with the notary of a [SignedTransaction] from the a map of [Party]s. It is a no-op
|
|
||||||
* if the notary is null.
|
|
||||||
*
|
|
||||||
* @return a new copy of the map, with the well known [Party] for the notary removed.
|
|
||||||
*/
|
|
||||||
fun <T> excludeNotary(map: Map<Party, T>, stx: SignedTransaction): Map<Party, T> = map.filterKeys { it != stx.notary }
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ import net.corda.core.contracts.Command
|
|||||||
import net.corda.core.contracts.StateAndContract
|
import net.corda.core.contracts.StateAndContract
|
||||||
import net.corda.core.contracts.requireThat
|
import net.corda.core.contracts.requireThat
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
|
import net.corda.core.identity.excludeHostNode
|
||||||
|
import net.corda.core.identity.groupAbstractPartyByWellKnownParty
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
@ -114,7 +116,7 @@ class CollectSignaturesFlowTests {
|
|||||||
val command = Command(DummyContract.Commands.Create(), myInputKeys)
|
val command = Command(DummyContract.Commands.Create(), myInputKeys)
|
||||||
val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), command)
|
val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), command)
|
||||||
val ptx = serviceHub.signInitialTransaction(builder)
|
val ptx = serviceHub.signInitialTransaction(builder)
|
||||||
val sessions = serviceHub.excludeMe(serviceHub.groupAbstractPartyByWellKnownParty(state.owners)).map { initiateFlow(it.key) }
|
val sessions = excludeHostNode(serviceHub, groupAbstractPartyByWellKnownParty(serviceHub, state.owners)).map { initiateFlow(it.key) }
|
||||||
val stx = subFlow(CollectSignaturesFlow(ptx, sessions, myInputKeys))
|
val stx = subFlow(CollectSignaturesFlow(ptx, sessions, myInputKeys))
|
||||||
return subFlow(FinalityFlow(stx))
|
return subFlow(FinalityFlow(stx))
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import net.corda.core.crypto.TransactionSignature
|
|||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
import net.corda.core.identity.AnonymousParty
|
import net.corda.core.identity.AnonymousParty
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
|
import net.corda.core.identity.excludeNotary
|
||||||
|
import net.corda.core.identity.groupPublicKeysByWellKnownParty
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
@ -112,7 +114,7 @@ object TwoPartyDealFlow {
|
|||||||
|
|
||||||
// DOCSTART 1
|
// DOCSTART 1
|
||||||
// Get signatures of other signers
|
// Get signatures of other signers
|
||||||
val sessionsForOtherSigners = serviceHub.excludeNotary(serviceHub.groupPublicKeysByWellKnownParty(ptxSignedByOtherSide.getMissingSigners()), ptxSignedByOtherSide).map { initiateFlow(it.key) }
|
val sessionsForOtherSigners = excludeNotary(groupPublicKeysByWellKnownParty(serviceHub, ptxSignedByOtherSide.getMissingSigners()), ptxSignedByOtherSide).map { initiateFlow(it.key) }
|
||||||
val stx = subFlow(CollectSignaturesFlow(ptxSignedByOtherSide, sessionsForOtherSigners, additionalSigningPubKeys))
|
val stx = subFlow(CollectSignaturesFlow(ptxSignedByOtherSide, sessionsForOtherSigners, additionalSigningPubKeys))
|
||||||
// DOCEND 1
|
// DOCEND 1
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@ package net.corda.irs.flows
|
|||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
|
import net.corda.core.identity.excludeHostNode
|
||||||
|
import net.corda.core.identity.groupAbstractPartyByWellKnownParty
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.utilities.ProgressTracker
|
import net.corda.core.utilities.ProgressTracker
|
||||||
import net.corda.finance.contracts.DealState
|
import net.corda.finance.contracts.DealState
|
||||||
@ -45,7 +47,7 @@ object AutoOfferFlow {
|
|||||||
require(serviceHub.networkMapCache.notaryIdentities.isNotEmpty()) { "No notary nodes registered" }
|
require(serviceHub.networkMapCache.notaryIdentities.isNotEmpty()) { "No notary nodes registered" }
|
||||||
val notary = serviceHub.networkMapCache.notaryIdentities.first() // TODO We should pass the notary as a parameter to the flow, not leave it to random choice.
|
val notary = serviceHub.networkMapCache.notaryIdentities.first() // TODO We should pass the notary as a parameter to the flow, not leave it to random choice.
|
||||||
// need to pick which ever party is not us
|
// need to pick which ever party is not us
|
||||||
val otherParty = serviceHub.excludeMe(serviceHub.groupAbstractPartyByWellKnownParty(dealToBeOffered.participants)).keys.single()
|
val otherParty = excludeHostNode(serviceHub, groupAbstractPartyByWellKnownParty(serviceHub, dealToBeOffered.participants)).keys.single()
|
||||||
progressTracker.currentStep = DEALING
|
progressTracker.currentStep = DEALING
|
||||||
val session = initiateFlow(otherParty)
|
val session = initiateFlow(otherParty)
|
||||||
val instigator = Instigator(
|
val instigator = Instigator(
|
||||||
|
Loading…
Reference in New Issue
Block a user