mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +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.isFulfilledBy
|
||||
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.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
@ -90,7 +92,7 @@ abstract class AbstractStateReplacementFlow {
|
||||
* Initiate sessions with parties we want signatures from.
|
||||
*/
|
||||
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
|
||||
|
@ -4,6 +4,7 @@ import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.crypto.TransactionSignature
|
||||
import net.corda.core.crypto.isFulfilledBy
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.groupPublicKeysByWellKnownParty
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
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 (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.
|
||||
require(sessionsToCollectFrom.map { it.counterparty }.toSet() == partyToKeysMap.keys) {
|
||||
"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) {
|
||||
val signingWellKnownIdentities = serviceHub.groupPublicKeysByWellKnownParty(stx.sigs.map(TransactionSignature::by))
|
||||
val signingWellKnownIdentities = groupPublicKeysByWellKnownParty(serviceHub, stx.sigs.map(TransactionSignature::by))
|
||||
require(otherSideSession.counterparty in signingWellKnownIdentities) {
|
||||
"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 net.corda.core.crypto.isFulfilledBy
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.groupAbstractPartyByWellKnownParty
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
@ -92,7 +93,7 @@ class FinalityFlow(val transaction: SignedTransaction,
|
||||
|
||||
private fun getPartiesToSend(ltx: LedgerTransaction): Set<Party> {
|
||||
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 {
|
||||
|
@ -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]
|
||||
*/
|
||||
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.requireThat
|
||||
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.TransactionBuilder
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
@ -114,7 +116,7 @@ class CollectSignaturesFlowTests {
|
||||
val command = Command(DummyContract.Commands.Create(), myInputKeys)
|
||||
val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), command)
|
||||
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))
|
||||
return subFlow(FinalityFlow(stx))
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import net.corda.core.crypto.TransactionSignature
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.core.identity.AnonymousParty
|
||||
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.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
@ -112,7 +114,7 @@ object TwoPartyDealFlow {
|
||||
|
||||
// DOCSTART 1
|
||||
// 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))
|
||||
// DOCEND 1
|
||||
|
||||
|
@ -2,6 +2,8 @@ package net.corda.irs.flows
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
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.utilities.ProgressTracker
|
||||
import net.corda.finance.contracts.DealState
|
||||
@ -45,7 +47,7 @@ object AutoOfferFlow {
|
||||
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.
|
||||
// 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
|
||||
val session = initiateFlow(otherParty)
|
||||
val instigator = Instigator(
|
||||
|
Loading…
Reference in New Issue
Block a user