R3NET-546: Improve the way CheckMembership operation is performed (#140)

This commit is contained in:
Viktor Kolomeyko 2017-12-05 10:49:57 +00:00 committed by GitHub
parent 60bde88777
commit fad29ff1f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 39 additions and 17 deletions

View File

@ -10,6 +10,8 @@ import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker
import net.corda.sample.businessnetwork.membership.MembershipAware
import net.corda.sample.businessnetwork.membership.CheckMembershipFlow
import net.corda.sample.businessnetwork.membership.CheckMembershipResult
import kotlin.reflect.jvm.jvmName
@InitiatingFlow
@ -28,15 +30,12 @@ class IOUFlow(val iouValue: Int,
/** The flow logic is encapsulated within the call() method. */
@Suspendable
override fun call(): SignedTransaction {
// Check whether the other party belongs to the membership list important for us.
otherParty.checkMembership(allowedMembershipName, this)
// Prior to creating any state - obtain consent from [otherParty] to borrow from us.
// Prior to creating any state, check on our side whether [otherParty] belongs to desired membership list.
// Also obtain consent from [otherParty] to borrow from us.
// This is done early enough in the flow such that if the other party rejects - do not do any unnecessary processing in this flow.
// Even if this is not done, later on upon signatures collection phase membership will be checked on the other side and
// transaction rejected if this doesn't hold. See [IOUFlowResponder] for more information.
otherParty.checkSharesSameMembershipWithUs(allowedMembershipName, this)
check(subFlow(CheckMembershipFlow(otherParty, allowedMembershipName)) == CheckMembershipResult.PASS)
// We retrieve the notary identity from the network map.
val notary = serviceHub.networkMapCache.notaryIdentities[0]

View File

@ -7,13 +7,14 @@ import net.corda.core.flows.FlowSession
import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.SignTransactionFlow
import net.corda.core.transactions.SignedTransaction
import net.corda.sample.businessnetwork.membership.CheckMembershipFlow
import net.corda.sample.businessnetwork.membership.MembershipAware
@InitiatedBy(IOUFlow::class)
class IOUFlowResponder(val otherPartySession: FlowSession) : FlowLogic<Unit>() {
class IOUFlowResponder(val otherPartySession: FlowSession) : FlowLogic<Unit>(), MembershipAware {
@Suspendable
override fun call() {
subFlow(CheckMembershipFlow(IOUFlow.allowedMembershipName, otherPartySession.counterparty))
otherPartySession.counterparty.checkMembership(IOUFlow.allowedMembershipName, this)
subFlow(object : SignTransactionFlow(otherPartySession, SignTransactionFlow.tracker()) {
override fun checkTransaction(stx: SignedTransaction) = requireThat {

View File

@ -1,11 +1,38 @@
package net.corda.sample.businessnetwork.membership
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.flows.FlowLogic
import net.corda.core.identity.AbstractParty
import net.corda.core.flows.FlowSession
import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.InitiatingFlow
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.serialization.CordaSerializable
import net.corda.core.utilities.unwrap
class CheckMembershipFlow(private val membershipName: CordaX500Name, private val counterParty: AbstractParty) : FlowLogic<Unit>(), MembershipAware {
override fun call() {
counterParty.checkMembership(membershipName, this)
@CordaSerializable
enum class CheckMembershipResult {
PASS,
FAIL
}
@InitiatingFlow
class CheckMembershipFlow(private val otherParty: Party, private val membershipName: CordaX500Name) : FlowLogic<CheckMembershipResult>(), MembershipAware {
@Suspendable
override fun call(): CheckMembershipResult {
otherParty.checkMembership(membershipName, this)
// This will trigger CounterpartyCheckMembershipFlow
val untrustworthyData = initiateFlow(otherParty).sendAndReceive<CheckMembershipResult>(membershipName)
return untrustworthyData.unwrap { it }
}
}
@InitiatedBy(CheckMembershipFlow::class)
class CounterpartyCheckMembershipFlow(private val otherPartySession: FlowSession) : FlowLogic<Unit>(), MembershipAware {
@Suspendable
override fun call() {
val membershipName = otherPartySession.receive<CordaX500Name>().unwrap { it }
otherPartySession.counterparty.checkMembership(membershipName, this)
otherPartySession.send(CheckMembershipResult.PASS)
}
}

View File

@ -4,7 +4,6 @@ import net.corda.core.flows.FlowException
import net.corda.core.flows.FlowLogic
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.node.ServiceHub
import net.corda.sample.businessnetwork.membership.internal.MembershipListProvider
@ -22,10 +21,6 @@ interface MembershipAware {
}
fun getMembershipList(listName: CordaX500Name, serviceHub: ServiceHub): MembershipList = MembershipListProvider.obtainMembershipList(listName, serviceHub.networkMapCache)
fun <T> Party.checkSharesSameMembershipWithUs(membershipName: CordaX500Name, initiatorFlow: FlowLogic<T>) {
initiatorFlow.stateMachine.initiateFlow(this, CheckMembershipFlow(membershipName, initiatorFlow.ourIdentity))
}
}
class MembershipViolationException(msg: String) : FlowException(msg)