diff --git a/core/src/main/kotlin/net/corda/core/flows/FinalityFlow.kt b/core/src/main/kotlin/net/corda/core/flows/FinalityFlow.kt index ba42e1393c..13643f0ed9 100644 --- a/core/src/main/kotlin/net/corda/core/flows/FinalityFlow.kt +++ b/core/src/main/kotlin/net/corda/core/flows/FinalityFlow.kt @@ -6,12 +6,12 @@ import net.corda.core.contracts.StateRef import net.corda.core.contracts.TransactionState import net.corda.core.crypto.isFulfilledBy import net.corda.core.identity.AbstractParty -import net.corda.core.crypto.toStringShort import net.corda.core.identity.Party import net.corda.core.internal.ResolveTransactionsFlow import net.corda.core.node.ServiceHub import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.SignedTransaction +import net.corda.core.utilities.NonEmptySet import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.toNonEmptySet @@ -36,9 +36,8 @@ import net.corda.core.utilities.toNonEmptySet * @param extraRecipients A list of additional participants to inform of the transaction. */ open class FinalityFlow(val transactions: Iterable, - val extraRecipients: Set, - override val progressTracker: ProgressTracker) : FlowLogic>() { - val extraParticipants: Set = extraRecipients.map { it -> Participant(it, it) }.toSet() + private val extraRecipients: Set, + override val progressTracker: ProgressTracker) : FlowLogic>() { constructor(transaction: SignedTransaction, extraParticipants: Set) : this(listOf(transaction), extraParticipants, tracker()) constructor(transaction: SignedTransaction) : this(listOf(transaction), emptySet(), tracker()) constructor(transaction: SignedTransaction, progressTracker: ProgressTracker) : this(listOf(transaction), emptySet(), progressTracker) @@ -54,8 +53,7 @@ open class FinalityFlow(val transactions: Iterable, fun tracker() = ProgressTracker(NOTARISING, BROADCASTING) } - open protected val me - get() = serviceHub.myInfo.legalIdentity + open protected val ourIdentity: Party get() = serviceHub.myInfo.legalIdentity @Suspendable @Throws(NotaryException::class) @@ -66,13 +64,16 @@ open class FinalityFlow(val transactions: Iterable, // Lookup the resolved transactions and use them to map each signed transaction to the list of participants. // Then send to the notary if needed, record locally and distribute. progressTracker.currentStep = NOTARISING - val notarisedTxns: List>> = resolveDependenciesOf(transactions) + val notarisedTxns: List>> = resolveDependenciesOf(transactions) .map { (stx, ltx) -> Pair(notariseAndRecord(stx), lookupParties(ltx)) } // Each transaction has its own set of recipients, but extra recipients get them all. progressTracker.currentStep = BROADCASTING for ((stx, parties) in notarisedTxns) { - broadcastTransaction(stx, (parties + extraParticipants).filter { it.wellKnown != me }) + val participants = (parties + extraRecipients).filter { it != ourIdentity }.toSet() + if (participants.isNotEmpty()) { + broadcastTransaction(stx, participants.toNonEmptySet()) + } } return notarisedTxns.map { it.first } } @@ -80,17 +81,13 @@ open class FinalityFlow(val transactions: Iterable, /** * Broadcast a transaction to the participants. By default calls [BroadcastTransactionFlow], however can be * overridden for more complex transaction delivery protocols (for example where not all parties know each other). - * This implementation will filter out any participants for whom there is no well known identity. * * @param participants the participants to send the transaction to. This is expected to include extra participants * and exclude the local node. */ @Suspendable - open protected fun broadcastTransaction(stx: SignedTransaction, participants: Iterable) { - val wellKnownParticipants = participants.map { it.wellKnown }.filterNotNull() - if (wellKnownParticipants.isNotEmpty()) { - subFlow(BroadcastTransactionFlow(stx, wellKnownParticipants.toNonEmptySet())) - } + open protected fun broadcastTransaction(stx: SignedTransaction, participants: NonEmptySet) { + subFlow(BroadcastTransactionFlow(stx, participants)) } @Suspendable @@ -109,7 +106,6 @@ open class FinalityFlow(val transactions: Iterable, val wtx = stx.tx val needsNotarisation = wtx.inputs.isNotEmpty() || wtx.timeWindow != null return needsNotarisation && hasNoNotarySignature(stx) - } private fun hasNoNotarySignature(stx: SignedTransaction): Boolean { @@ -121,19 +117,14 @@ open class FinalityFlow(val transactions: Iterable, /** * Resolve the parties involved in a transaction. * - * @return the set of participants and their resolved well known identities (where known). + * The default implementation throws an exception if an unknown party is encountered. */ - open protected fun lookupParties(ltx: LedgerTransaction): Set { + open protected fun lookupParties(ltx: LedgerTransaction): List { // Calculate who is meant to see the results based on the participants involved. - return extractParticipants(ltx) - .map(this::partyFromAnonymous) - .map { participant -> - if (participant.wellKnown != null) - participant - else - throw IllegalArgumentException("Could not resolve well known identity of participant ${participant.participant.owningKey.toStringShort()}") - } - .toSet() + return extractParticipants(ltx).map { + serviceHub.identityService.partyFromAnonymous(it) + ?: throw IllegalArgumentException("Could not resolve well known identity of participant $it") + } } /** @@ -144,13 +135,6 @@ open class FinalityFlow(val transactions: Iterable, return ltx.outputStates.flatMap { it.participants } + ltx.inputStates.flatMap { it.participants } } - /** - * Helper function which wraps [IdentityService.partyFromAnonymous] so it can be called as a lambda function. - */ - protected fun partyFromAnonymous(anon: AbstractParty): Participant { - return Participant(anon, serviceHub.identityService.partyFromAnonymous(anon)) - } - private fun resolveDependenciesOf(signedTransactions: Iterable): List> { // Make sure the dependencies come before the dependers. val sorted = ResolveTransactionsFlow.topologicalSort(signedTransactions.toList()) @@ -173,6 +157,4 @@ open class FinalityFlow(val transactions: Iterable, stx to ltx } } - - data class Participant(val participant: AbstractParty, val wellKnown: Party?) } diff --git a/core/src/main/kotlin/net/corda/core/flows/ManualFinalityFlow.kt b/core/src/main/kotlin/net/corda/core/flows/ManualFinalityFlow.kt index f91b38b85f..5fe7aa2745 100644 --- a/core/src/main/kotlin/net/corda/core/flows/ManualFinalityFlow.kt +++ b/core/src/main/kotlin/net/corda/core/flows/ManualFinalityFlow.kt @@ -10,11 +10,11 @@ import net.corda.core.utilities.ProgressTracker * participating parties must be provided manually. * * @param transactions What to commit. - * @param extraRecipients A list of additional participants to inform of the transaction. + * @param recipients List of participants to inform of the transaction. */ class ManualFinalityFlow(transactions: Iterable, - recipients: Set, - progressTracker: ProgressTracker) : FinalityFlow(transactions, recipients, progressTracker) { + recipients: Set, + progressTracker: ProgressTracker) : FinalityFlow(transactions, recipients, progressTracker) { constructor(transaction: SignedTransaction, extraParticipants: Set) : this(listOf(transaction), extraParticipants, tracker()) - override fun lookupParties(ltx: LedgerTransaction): Set = emptySet() -} \ No newline at end of file + override fun lookupParties(ltx: LedgerTransaction): List = emptyList() +}