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.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.ProgressTracker
import net.corda.sample.businessnetwork.membership.MembershipAware 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 import kotlin.reflect.jvm.jvmName
@InitiatingFlow @InitiatingFlow
@ -28,15 +30,12 @@ class IOUFlow(val iouValue: Int,
/** The flow logic is encapsulated within the call() method. */ /** The flow logic is encapsulated within the call() method. */
@Suspendable @Suspendable
override fun call(): SignedTransaction { override fun call(): SignedTransaction {
// Prior to creating any state, check on our side whether [otherParty] belongs to desired membership list.
// Check whether the other party belongs to the membership list important for us. // Also obtain consent from [otherParty] to borrow from us.
otherParty.checkMembership(allowedMembershipName, this)
// Prior to creating any state - 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. // 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 // 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. // 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. // We retrieve the notary identity from the network map.
val notary = serviceHub.networkMapCache.notaryIdentities[0] 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.InitiatedBy
import net.corda.core.flows.SignTransactionFlow import net.corda.core.flows.SignTransactionFlow
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.sample.businessnetwork.membership.CheckMembershipFlow import net.corda.sample.businessnetwork.membership.MembershipAware
@InitiatedBy(IOUFlow::class) @InitiatedBy(IOUFlow::class)
class IOUFlowResponder(val otherPartySession: FlowSession) : FlowLogic<Unit>() { class IOUFlowResponder(val otherPartySession: FlowSession) : FlowLogic<Unit>(), MembershipAware {
@Suspendable @Suspendable
override fun call() { override fun call() {
subFlow(CheckMembershipFlow(IOUFlow.allowedMembershipName, otherPartySession.counterparty))
otherPartySession.counterparty.checkMembership(IOUFlow.allowedMembershipName, this)
subFlow(object : SignTransactionFlow(otherPartySession, SignTransactionFlow.tracker()) { subFlow(object : SignTransactionFlow(otherPartySession, SignTransactionFlow.tracker()) {
override fun checkTransaction(stx: SignedTransaction) = requireThat { override fun checkTransaction(stx: SignedTransaction) = requireThat {

View File

@ -1,11 +1,38 @@
package net.corda.sample.businessnetwork.membership package net.corda.sample.businessnetwork.membership
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.flows.FlowLogic 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.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 { @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() { override fun call() {
counterParty.checkMembership(membershipName, this) 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.flows.FlowLogic
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.sample.businessnetwork.membership.internal.MembershipListProvider 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 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) class MembershipViolationException(msg: String) : FlowException(msg)