Changed FlowLogic.ourIdentity to return Party and added FlowLogic.ourIdentityAndCert which returns PartyAndCertificate. (#1537)

Updated code base to make use of these instead of chooseIdentity(). Also improved the serialisation of fiber checkpoints so that it doesn't store the entire cert parth of this identity.
This commit is contained in:
Shams Asari 2017-09-18 15:28:23 +01:00 committed by josecoll
parent 8f86068807
commit 8e0b8477af
35 changed files with 178 additions and 165 deletions

2
.idea/compiler.xml generated
View File

@ -12,6 +12,8 @@
<module name="buildSrc_test" target="1.8" />
<module name="client_main" target="1.8" />
<module name="client_test" target="1.8" />
<module name="confidential-identities_main" target="1.8" />
<module name="confidential-identities_test" target="1.8" />
<module name="corda-project_main" target="1.8" />
<module name="corda-project_test" target="1.8" />
<module name="corda-webserver_integrationTest" target="1.8" />

View File

@ -18,8 +18,8 @@ import net.corda.core.utilities.unwrap
*/
@StartableByRPC
@InitiatingFlow
class SwapIdentitiesFlow(val otherSide: Party,
val revocationEnabled: Boolean,
class SwapIdentitiesFlow(private val otherSide: Party,
private val revocationEnabled: Boolean,
override val progressTracker: ProgressTracker) : FlowLogic<LinkedHashMap<Party, AnonymousParty>>() {
constructor(otherSide: Party) : this(otherSide, false, tracker())
@ -39,7 +39,7 @@ class SwapIdentitiesFlow(val otherSide: Party,
@Suspendable
override fun call(): LinkedHashMap<Party, AnonymousParty> {
progressTracker.currentStep = AWAITING_KEY
val legalIdentityAnonymous = serviceHub.keyManagementService.freshKeyAndCert(ourIdentity, revocationEnabled)
val legalIdentityAnonymous = serviceHub.keyManagementService.freshKeyAndCert(ourIdentityAndCert, revocationEnabled)
// Special case that if we're both parties, a single identity is generated
val identities = LinkedHashMap<Party, AnonymousParty>()
@ -49,7 +49,7 @@ class SwapIdentitiesFlow(val otherSide: Party,
val anonymousOtherSide = sendAndReceive<PartyAndCertificate>(otherSide, legalIdentityAnonymous).unwrap { confidentialIdentity ->
validateAndRegisterIdentity(serviceHub.identityService, otherSide, confidentialIdentity)
}
identities.put(ourIdentity.party, legalIdentityAnonymous.party.anonymise())
identities.put(ourIdentity, legalIdentityAnonymous.party.anonymise())
identities.put(otherSide, anonymousOtherSide.party.anonymise())
}
return identities

View File

@ -16,10 +16,10 @@ class SwapIdentitiesHandler(val otherSide: Party, val revocationEnabled: Boolean
override val progressTracker: ProgressTracker = ProgressTracker(SENDING_KEY)
@Suspendable
override fun call(): Unit {
override fun call() {
val revocationEnabled = false
progressTracker.currentStep = SENDING_KEY
val legalIdentityAnonymous = serviceHub.keyManagementService.freshKeyAndCert(ourIdentity, revocationEnabled)
val legalIdentityAnonymous = serviceHub.keyManagementService.freshKeyAndCert(ourIdentityAndCert, revocationEnabled)
sendAndReceive<PartyAndCertificate>(otherSide, legalIdentityAnonymous).unwrap { confidentialIdentity ->
SwapIdentitiesFlow.validateAndRegisterIdentity(serviceHub.identityService, otherSide, confidentialIdentity)
}

View File

@ -62,13 +62,13 @@ open class FinalityFlow(val transactions: Iterable<SignedTransaction>,
// 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<Pair<SignedTransaction, List<Party>>> = resolveDependenciesOf(transactions)
val notarisedTxns: List<Pair<SignedTransaction, Set<Party>>> = 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) {
val participants = (parties + extraRecipients).filter { it != ourIdentity.party }.toSet()
val participants = (parties + extraRecipients).filter { !serviceHub.myInfo.isLegalIdentity(it) }.toSet()
if (participants.isNotEmpty()) {
broadcastTransaction(stx, participants.toNonEmptySet())
}
@ -117,12 +117,12 @@ open class FinalityFlow(val transactions: Iterable<SignedTransaction>,
*
* The default implementation throws an exception if an unknown party is encountered.
*/
open protected fun lookupParties(ltx: LedgerTransaction): List<Party> {
open protected fun lookupParties(ltx: LedgerTransaction): Set<Party> {
// Calculate who is meant to see the results based on the participants involved.
return extractParticipants(ltx).map {
serviceHub.identityService.partyFromAnonymous(it)
?: throw IllegalArgumentException("Could not resolve well known identity of participant $it")
}
}.toSet()
}
/**

View File

@ -7,6 +7,7 @@ import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.abbreviate
import net.corda.core.messaging.DataFeed
import net.corda.core.node.NodeInfo
import net.corda.core.node.ServiceHub
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.SignedTransaction
@ -58,10 +59,24 @@ abstract class FlowLogic<out T> {
fun initiateFlow(party: Party): FlowSession = stateMachine.initiateFlow(party, flowUsedForSessions)
/**
* Specifies our identity in the flow. With node's multiple identities we can choose which one to use for communication.
* Defaults to the first one from [NodeInfo.legalIdentitiesAndCerts].
* Specifies the identity, with certificate, to use for this flow. This will be one of the multiple identities that
* belong to this node.
* @see NodeInfo.legalIdentitiesAndCerts
*
* Note: The current implementation returns the single identity of the node. This will change once multiple identities
* is implemented.
*/
val ourIdentity: PartyAndCertificate get() = stateMachine.ourIdentity
val ourIdentityAndCert: PartyAndCertificate get() = stateMachine.ourIdentityAndCert
/**
* Specifies the identity to use for this flow. This will be one of the multiple identities that belong to this node.
* This is the same as calling `ourIdentityAndCert.party`.
* @see NodeInfo.legalIdentities
*
* Note: The current implementation returns the single identity of the node. This will change once multiple identities
* is implemented.
*/
val ourIdentity: Party get() = ourIdentityAndCert.party
/**
* Returns a [FlowInfo] object describing the flow [otherParty] is using. With [FlowInfo.flowVersion] it

View File

@ -16,5 +16,5 @@ class ManualFinalityFlow(transactions: Iterable<SignedTransaction>,
recipients: Set<Party>,
progressTracker: ProgressTracker) : FinalityFlow(transactions, recipients, progressTracker) {
constructor(transaction: SignedTransaction, extraParticipants: Set<Party>) : this(listOf(transaction), extraParticipants, tracker())
override fun lookupParties(ltx: LedgerTransaction): List<Party> = emptyList()
override fun lookupParties(ltx: LedgerTransaction): Set<Party> = emptySet()
}

View File

@ -50,5 +50,5 @@ interface FlowStateMachine<R> {
val id: StateMachineRunId
val resultFuture: CordaFuture<R>
val flowInitiator: FlowInitiator
val ourIdentity: PartyAndCertificate
val ourIdentityAndCert: PartyAndCertificate
}

View File

@ -38,7 +38,7 @@ data class NodeInfo(val addresses: List<NetworkHostAndPort>,
return _legalIdentities ?: legalIdentitiesAndCerts.map { it.party }.also { _legalIdentities = it }
}
/** Returns true iff [party] is one of the identities of this node. */
/** Returns true if [party] is one of the identities of this node, else false. */
fun isLegalIdentity(party: Party): Boolean = party in legalIdentities
fun serviceIdentities(type: ServiceType): List<Party> {

View File

@ -12,10 +12,10 @@ import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.unwrap
import net.corda.node.internal.StartedNode
import net.corda.testing.MINI_CORP_KEY
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.contracts.DummyContract
import net.corda.testing.chooseIdentity
import net.corda.testing.chooseIdentityAndCert
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.contracts.DummyContract
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockServices
import org.junit.After
@ -77,9 +77,7 @@ class CollectSignaturesFlowTests {
}
val stx = subFlow(flow)
val ftx = waitForLedgerCommit(stx.id)
return ftx
return waitForLedgerCommit(stx.id)
}
}
@ -91,14 +89,12 @@ class CollectSignaturesFlowTests {
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
val myInputKeys = state.participants.map { it.owningKey }
val myKeys = myInputKeys + (identities[serviceHub.myInfo.chooseIdentity()] ?: serviceHub.myInfo.chooseIdentity()).owningKey
val myKeys = myInputKeys + (identities[ourIdentity] ?: ourIdentity).owningKey
val command = Command(DummyContract.Commands.Create(), myInputKeys)
val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), command)
val ptx = serviceHub.signInitialTransaction(builder)
val stx = subFlow(CollectSignaturesFlow(ptx, myKeys))
val ftx = subFlow(FinalityFlow(stx)).single()
return ftx
return subFlow(FinalityFlow(stx)).single()
}
}
}
@ -117,9 +113,7 @@ class CollectSignaturesFlowTests {
val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), command)
val ptx = serviceHub.signInitialTransaction(builder)
val stx = subFlow(CollectSignaturesFlow(ptx, myInputKeys))
val ftx = subFlow(FinalityFlow(stx)).single()
return ftx
return subFlow(FinalityFlow(stx)).single()
}
}

View File

@ -48,8 +48,7 @@ data class TradeApprovalContract(val blank: Unit? = null) : Contract {
val counterparty: Party,
val state: WorkflowState = WorkflowState.NEW,
override val linearId: UniqueIdentifier = UniqueIdentifier(tradeId)) : LinearState {
val parties: List<Party> get() = listOf(source, counterparty)
override val participants: List<AbstractParty> get() = parties
override val participants: List<AbstractParty> get() = listOf(source, counterparty)
}
/**
@ -96,29 +95,26 @@ data class TradeApprovalContract(val blank: Unit? = null) : Contract {
* The protocol then sends a copy to the other node. We don't require the other party to sign
* as their approval/rejection is to follow.
*/
class SubmitTradeApprovalFlow(val tradeId: String,
val counterparty: Party) : FlowLogic<StateAndRef<TradeApprovalContract.State>>() {
class SubmitTradeApprovalFlow(private val tradeId: String,
private val counterparty: Party) : FlowLogic<StateAndRef<TradeApprovalContract.State>>() {
@Suspendable
override fun call(): StateAndRef<TradeApprovalContract.State> {
// Manufacture an initial state
val tradeProposal = TradeApprovalContract.State(
tradeId,
serviceHub.myInfo.chooseIdentity(),
counterparty)
val tradeProposal = TradeApprovalContract.State(tradeId, ourIdentity, counterparty)
// identify a notary. This might also be done external to the flow
val notary = serviceHub.networkMapCache.getAnyNotary()
// Create the TransactionBuilder and populate with the new state.
val tx = TransactionBuilder(notary)
.withItems(StateAndContract(tradeProposal, TRADE_APPROVAL_PROGRAM_ID), Command(TradeApprovalContract.Commands.Issue(), listOf(tradeProposal.source.owningKey)))
val tx = TransactionBuilder(notary).withItems(
StateAndContract(tradeProposal, TRADE_APPROVAL_PROGRAM_ID),
Command(TradeApprovalContract.Commands.Issue(), listOf(tradeProposal.source.owningKey)))
tx.setTimeWindow(serviceHub.clock.instant(), 60.seconds)
// We can automatically sign as there is no untrusted data.
val signedTx = serviceHub.signInitialTransaction(tx)
// Notarise and distribute.
subFlow(FinalityFlow(signedTx, setOf(serviceHub.myInfo.chooseIdentity(), counterparty)))
subFlow(FinalityFlow(signedTx, setOf(ourIdentity, counterparty)))
// Return the initial state
return signedTx.tx.outRef(0)
}
}
/**
@ -126,7 +122,7 @@ class SubmitTradeApprovalFlow(val tradeId: String,
* end up with a fully signed copy of the state either as APPROVED, or REJECTED
*/
@InitiatingFlow
class SubmitCompletionFlow(val ref: StateRef, val verdict: WorkflowState) : FlowLogic<StateAndRef<TradeApprovalContract.State>>() {
class SubmitCompletionFlow(private val ref: StateRef, private val verdict: WorkflowState) : FlowLogic<StateAndRef<TradeApprovalContract.State>>() {
init {
require(verdict in setOf(WorkflowState.APPROVED, WorkflowState.REJECTED)) {
"Verdict must be a final state"
@ -171,7 +167,7 @@ class SubmitCompletionFlow(val ref: StateRef, val verdict: WorkflowState) : Flow
latestRecord,
StateAndContract(newState, TRADE_APPROVAL_PROGRAM_ID),
Command(TradeApprovalContract.Commands.Completed(),
listOf(serviceHub.myInfo.chooseIdentity().owningKey, latestRecord.state.data.source.owningKey)))
listOf(ourIdentity.owningKey, latestRecord.state.data.source.owningKey)))
tx.setTimeWindow(serviceHub.clock.instant(), 60.seconds)
// We can sign this transaction immediately as we have already checked all the fields and the decision
// is ultimately a manual one from the caller.
@ -197,7 +193,7 @@ class SubmitCompletionFlow(val ref: StateRef, val verdict: WorkflowState) : Flow
subFlow(FinalityFlow(allPartySignedTx, setOf(latestRecord.state.data.source, latestRecord.state.data.counterparty)))
// DOCEND 4
// Return back the details of the completed state/transaction.
return allPartySignedTx.tx.outRef<TradeApprovalContract.State>(0)
return allPartySignedTx.tx.outRef(0)
}
}
@ -207,14 +203,14 @@ class SubmitCompletionFlow(val ref: StateRef, val verdict: WorkflowState) : Flow
* transaction to the ledger.
*/
@InitiatedBy(SubmitCompletionFlow::class)
class RecordCompletionFlow(val source: Party) : FlowLogic<Unit>() {
class RecordCompletionFlow(private val source: Party) : FlowLogic<Unit>() {
@Suspendable
override fun call(): Unit {
override fun call() {
// DOCSTART 3
// First we receive the verdict transaction signed by their single key
val completeTx = receive<SignedTransaction>(source).unwrap {
// Check the transaction is signed apart from our own key and the notary
it.verifySignaturesExcept(serviceHub.myInfo.chooseIdentity().owningKey, it.tx.notary!!.owningKey)
it.verifySignaturesExcept(ourIdentity.owningKey, it.tx.notary!!.owningKey)
// Check the transaction data is correctly formed
val ltx = it.toLedgerTransaction(serviceHub, false)
ltx.verify()

View File

@ -26,7 +26,9 @@ import java.util.*
* issuer.
*/
@StartableByRPC
class CashExitFlow(val amount: Amount<Currency>, val issuerRef: OpaqueBytes, progressTracker: ProgressTracker) : AbstractCashFlow<AbstractCashFlow.Result>(progressTracker) {
class CashExitFlow(private val amount: Amount<Currency>,
private val issuerRef: OpaqueBytes,
progressTracker: ProgressTracker) : AbstractCashFlow<AbstractCashFlow.Result>(progressTracker) {
constructor(amount: Amount<Currency>, issueRef: OpaqueBytes) : this(amount, issueRef, tracker())
constructor(request: ExitRequest) : this(request.amount, request.issueRef, tracker())
@ -43,8 +45,9 @@ class CashExitFlow(val amount: Amount<Currency>, val issuerRef: OpaqueBytes, pro
override fun call(): AbstractCashFlow.Result {
progressTracker.currentStep = GENERATING_TX
val builder = TransactionBuilder(notary = null as Party?)
val issuer = ourIdentity.party.ref(issuerRef)
val exitStates = CashSelection.getInstance({serviceHub.jdbcSession().metaData}).unconsumedCashStatesForSpending(serviceHub, amount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference))
val issuer = ourIdentity.ref(issuerRef)
val exitStates = CashSelection.getInstance { serviceHub.jdbcSession().metaData }
.unconsumedCashStatesForSpending(serviceHub, amount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference))
val signers = try {
Cash().generateExit(
builder,
@ -61,9 +64,7 @@ class CashExitFlow(val amount: Amount<Currency>, val issuerRef: OpaqueBytes, pro
// TODO: Is it safe to drop participants we don't know how to contact? Does not knowing how to contact them
// count as a reason to fail?
val participants: Set<Party> = inputStates
.filterIsInstance<Cash.State>()
.map { serviceHub.identityService.partyFromAnonymous(it.owner) }
.filterNotNull()
.mapNotNull { serviceHub.identityService.partyFromAnonymous(it.state.data.owner) }
.toSet()
// Sign transaction
progressTracker.currentStep = SIGNING_TX

View File

@ -25,9 +25,9 @@ import java.util.*
* @param notary the notary to set on the output states.
*/
@StartableByRPC
class CashIssueFlow(val amount: Amount<Currency>,
val issuerBankPartyRef: OpaqueBytes,
val notary: Party,
class CashIssueFlow(private val amount: Amount<Currency>,
private val issuerBankPartyRef: OpaqueBytes,
private val notary: Party,
progressTracker: ProgressTracker) : AbstractCashFlow<AbstractCashFlow.Result>(progressTracker) {
constructor(amount: Amount<Currency>,
issuerBankPartyRef: OpaqueBytes,
@ -38,13 +38,13 @@ class CashIssueFlow(val amount: Amount<Currency>,
override fun call(): AbstractCashFlow.Result {
progressTracker.currentStep = GENERATING_TX
val builder = TransactionBuilder(notary)
val issuer = ourIdentity.party.ref(issuerBankPartyRef)
val signers = Cash().generateIssue(builder, amount.issuedBy(issuer), ourIdentity.party, notary)
val issuer = ourIdentity.ref(issuerBankPartyRef)
val signers = Cash().generateIssue(builder, amount.issuedBy(issuer), ourIdentity, notary)
progressTracker.currentStep = SIGNING_TX
val tx = serviceHub.signInitialTransaction(builder, signers)
progressTracker.currentStep = FINALISING_TX
subFlow(FinalityFlow(tx))
return Result(tx, ourIdentity.party)
val notarised = subFlow(FinalityFlow(tx)).single()
return Result(notarised, ourIdentity)
}
@CordaSerializable

View File

@ -9,7 +9,6 @@ import net.corda.core.flows.CollectSignaturesFlow
import net.corda.core.flows.FinalityFlow
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.SignTransactionFlow
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.Party
import net.corda.core.node.NodeInfo
@ -58,8 +57,8 @@ object TwoPartyDealFlow {
@Suspendable override fun call(): SignedTransaction {
progressTracker.currentStep = GENERATING_ID
val txIdentities = subFlow(SwapIdentitiesFlow(otherParty))
val anonymousMe = txIdentities.get(ourIdentity.party) ?: ourIdentity.party.anonymise()
val anonymousCounterparty = txIdentities.get(otherParty) ?: otherParty.anonymise()
val anonymousMe = txIdentities[ourIdentity] ?: ourIdentity.anonymise()
val anonymousCounterparty = txIdentities[otherParty] ?: otherParty.anonymise()
progressTracker.currentStep = SENDING_PROPOSAL
// Make the first message we'll send to kick off the flow.
val hello = Handshake(payload, anonymousMe, anonymousCounterparty)
@ -122,7 +121,7 @@ object TwoPartyDealFlow {
logger.trace { "Got signatures from other party, verifying ... " }
progressTracker.currentStep = RECORDING
val ftx = subFlow(FinalityFlow(stx, setOf(otherParty, ourIdentity.party))).single()
val ftx = subFlow(FinalityFlow(stx, setOf(otherParty, ourIdentity))).single()
logger.trace { "Recorded transaction." }
@ -154,13 +153,15 @@ object TwoPartyDealFlow {
val wellKnownOtherParty = serviceHub.identityService.partyFromAnonymous(it.primaryIdentity)
val wellKnownMe = serviceHub.identityService.partyFromAnonymous(it.secondaryIdentity)
require(wellKnownOtherParty == otherParty)
require(wellKnownMe == ourIdentity.party)
require(wellKnownMe == ourIdentity)
validateHandshake(it)
}
}
@Suspendable protected abstract fun validateHandshake(handshake: Handshake<U>): Handshake<U>
@Suspendable protected abstract fun assembleSharedTX(handshake: Handshake<U>): Triple<TransactionBuilder, List<PublicKey>, List<TransactionSignature>>
@Suspendable
protected abstract fun validateHandshake(handshake: Handshake<U>): Handshake<U>
@Suspendable
protected abstract fun assembleSharedTX(handshake: Handshake<U>): Triple<TransactionBuilder, List<PublicKey>, List<TransactionSignature>>
}
@CordaSerializable
@ -173,7 +174,7 @@ object TwoPartyDealFlow {
override val payload: AutoOffer,
override val progressTracker: ProgressTracker = Primary.tracker()) : Primary() {
override val notaryNode: NodeInfo get() =
serviceHub.networkMapCache.notaryNodes.filter { it.notaryIdentity == payload.notary }.single()
serviceHub.networkMapCache.notaryNodes.single { it.notaryIdentity == payload.notary }
@Suspendable override fun checkProposal(stx: SignedTransaction) = requireThat {
// Add some constraints here.
@ -201,7 +202,7 @@ object TwoPartyDealFlow {
// We set the transaction's time-window: it may be that none of the contracts need this!
// But it can't hurt to have one.
ptx.setTimeWindow(serviceHub.clock.instant(), 30.seconds)
return Triple(ptx, arrayListOf(deal.participants.single { it == ourIdentity.party as AbstractParty }.owningKey), emptyList())
return Triple(ptx, arrayListOf(deal.participants.single { it is Party && serviceHub.myInfo.isLegalIdentity(it) }.owningKey), emptyList())
}
}
}

View File

@ -1,10 +1,6 @@
package net.corda.finance.flows
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.contracts.Amount
import net.corda.core.contracts.OwnableState
import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.withoutIssuer
import net.corda.core.contracts.*
import net.corda.core.flows.*
import net.corda.core.identity.Party
@ -103,7 +99,9 @@ object TwoPartyTradeFlow {
val states: Iterable<ContractState> = (stx.tx.inputs.map { serviceHub.loadState(it).data } + stx.tx.outputs.map { it.data })
states.forEach { state ->
state.participants.forEach { anon ->
require(serviceHub.identityService.partyFromAnonymous(anon) != null) { "Transaction state ${state} involves unknown participant ${anon}" }
require(serviceHub.identityService.partyFromAnonymous(anon) != null) {
"Transaction state $state involves unknown participant $anon"
}
}
}
@ -129,12 +127,13 @@ object TwoPartyTradeFlow {
// express flow state machines on top of the messaging layer.
}
open class Buyer(val otherParty: Party,
val notary: Party,
val acceptablePrice: Amount<Currency>,
val typeToBuy: Class<out OwnableState>,
val anonymous: Boolean) : FlowLogic<SignedTransaction>() {
constructor(otherParty: Party, notary: Party, acceptablePrice: Amount<Currency>, typeToBuy: Class<out OwnableState>): this(otherParty, notary, acceptablePrice, typeToBuy, true)
open class Buyer(private val otherParty: Party,
private val notary: Party,
private val acceptablePrice: Amount<Currency>,
private val typeToBuy: Class<out OwnableState>,
private val anonymous: Boolean) : FlowLogic<SignedTransaction>() {
constructor(otherParty: Party, notary: Party, acceptablePrice: Amount<Currency>, typeToBuy: Class<out OwnableState>) :
this(otherParty, notary, acceptablePrice, typeToBuy, true)
// DOCSTART 2
object RECEIVING : ProgressTracker.Step("Waiting for seller trading info")
@ -161,9 +160,9 @@ object TwoPartyTradeFlow {
// Create the identity we'll be paying to, and send the counterparty proof we own the identity
val buyerAnonymousIdentity = if (anonymous)
serviceHub.keyManagementService.freshKeyAndCert(ourIdentity, false)
serviceHub.keyManagementService.freshKeyAndCert(ourIdentityAndCert, false)
else
ourIdentity
ourIdentityAndCert
// Put together a proposed transaction that performs the trade, and sign it.
progressTracker.currentStep = SIGNING
val (ptx, cashSigningPubKeys) = assembleSharedTX(assetForSale, tradeRequest, buyerAnonymousIdentity)

View File

@ -11,7 +11,6 @@ import net.corda.testing.BOB
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.aliceBobAndNotary
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyState
import net.corda.testing.driver.driver
import net.corda.testing.dummyCommand
@ -24,17 +23,20 @@ import kotlin.test.assertEquals
*/
class LargeTransactionsTest {
@StartableByRPC @InitiatingFlow
class SendLargeTransactionFlow(val hash1: SecureHash, val hash2: SecureHash, val hash3: SecureHash, val hash4: SecureHash) : FlowLogic<Unit>() {
class SendLargeTransactionFlow(private val hash1: SecureHash,
private val hash2: SecureHash,
private val hash3: SecureHash,
private val hash4: SecureHash) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
val tx = TransactionBuilder(notary = DUMMY_NOTARY)
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
.addCommand(dummyCommand(serviceHub.myInfo.chooseIdentity().owningKey))
.addCommand(dummyCommand(ourIdentity.owningKey))
.addAttachment(hash1)
.addAttachment(hash2)
.addAttachment(hash3)
.addAttachment(hash4)
val stx = serviceHub.signInitialTransaction(tx, serviceHub.myInfo.chooseIdentity().owningKey)
val stx = serviceHub.signInitialTransaction(tx, ourIdentity.owningKey)
// Send to the other side and wait for it to trigger resolution from us.
val bob = serviceHub.identityService.partyFromX500Name(BOB.name)!!
subFlow(SendTransactionFlow(bob, stx))

View File

@ -140,7 +140,7 @@ class SendMessageFlow(private val message: Message) : FlowLogic<SignedTransactio
progressTracker.currentStep = GENERATING_TRANSACTION
val messageState = MessageState(message = message, by = serviceHub.myInfo.chooseIdentity())
val messageState = MessageState(message = message, by = ourIdentity)
val txCommand = Command(MessageContract.Commands.Send(), messageState.participants.map { it.owningKey })
val txBuilder = TransactionBuilder(notary).withItems(StateAndContract(messageState, MESSAGE_CONTRACT_PROGRAM_ID), txCommand)

View File

@ -731,9 +731,8 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
return cordappServices.getInstance(type) ?: throw IllegalArgumentException("Corda service ${type.name} does not exist")
}
override fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate?): FlowStateMachineImpl<T> {
check(me == null || me in myInfo.legalIdentitiesAndCerts) { "Attempt to start a flow with legal identity not belonging to this node." }
return serverThread.fetchFrom { smm.add(logic, flowInitiator, me) }
override fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator, ourIdentity: Party?): FlowStateMachineImpl<T> {
return serverThread.fetchFrom { smm.add(logic, flowInitiator, ourIdentity) }
}
override fun getFlowFactory(initiatingFlowClass: Class<out FlowLogic<*>>): InitiatedFlowFactory<*>? {

View File

@ -10,7 +10,6 @@ import net.corda.core.flows.StartableByRPC
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.messaging.*
import net.corda.core.node.NodeInfo
import net.corda.core.node.services.NetworkMapCache
@ -143,11 +142,11 @@ class CordaRPCOpsImpl(
private fun <T> startFlow(logicType: Class<out FlowLogic<T>>, args: Array<out Any?>): FlowStateMachineImpl<T> {
require(logicType.isAnnotationPresent(StartableByRPC::class.java)) { "${logicType.name} was not designed for RPC" }
val me = services.myInfo.legalIdentitiesAndCerts.first() // TODO RPC flows should have mapping user -> identity that should be resolved automatically on starting flow.
val rpcContext = getRpcContext()
rpcContext.requirePermission(startFlowPermission(logicType))
val currentUser = FlowInitiator.RPC(rpcContext.currentUser.username)
return services.invokeFlowAsync(logicType, currentUser, me, *args)
// TODO RPC flows should have mapping user -> identity that should be resolved automatically on starting flow.
return services.invokeFlowAsync(logicType, currentUser, *args)
}
override fun attachmentExists(id: SecureHash): Boolean {

View File

@ -1,16 +1,12 @@
package net.corda.node.services
import co.paralleluniverse.fibers.Suspendable
import net.corda.confidential.SwapIdentitiesFlow
import net.corda.core.flows.AbstractStateReplacementFlow
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.ReceiveTransactionFlow
import net.corda.core.flows.StateReplacementException
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.unwrap
// TODO: We should have a whitelist of contracts we're willing to accept at all, and reject if the transaction
// includes us in any outside that list. Potentially just if it includes any outside that list at all.
@ -32,7 +28,7 @@ class NotaryChangeHandler(otherSide: Party) : AbstractStateReplacementFlow.Accep
* and is also in a geographically convenient location we can just automatically approve the change.
* TODO: In more difficult cases this should call for human attention to manually verify and approve the proposal
*/
override fun verifyProposal(stx: SignedTransaction, proposal: AbstractStateReplacementFlow.Proposal<Party>): Unit {
override fun verifyProposal(stx: SignedTransaction, proposal: AbstractStateReplacementFlow.Proposal<Party>) {
val state = proposal.stateRef
val proposedTx = stx.resolveNotaryChangeTransaction(serviceHub)
val newNotary = proposal.modification

View File

@ -6,7 +6,6 @@ import net.corda.core.flows.FlowInitiator
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StateMachineRunId
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.VisibleForTesting
import net.corda.core.messaging.DataFeed
@ -118,7 +117,7 @@ interface ServiceHubInternal : ServiceHub {
* Starts an already constructed flow. Note that you must be on the server thread to call this method.
* @param flowInitiator indicates who started the flow, see: [FlowInitiator].
*/
fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate? = null): FlowStateMachineImpl<T>
fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator, ourIdentity: Party? = null): FlowStateMachineImpl<T>
/**
* Will check [logicType] and [args] against a whitelist and if acceptable then construct and initiate the flow.
@ -131,12 +130,11 @@ interface ServiceHubInternal : ServiceHub {
fun <T> invokeFlowAsync(
logicType: Class<out FlowLogic<T>>,
flowInitiator: FlowInitiator,
me: PartyAndCertificate? = null,
vararg args: Any?): FlowStateMachineImpl<T> {
val logicRef = FlowLogicRefFactoryImpl.createForRPC(logicType, *args)
@Suppress("UNCHECKED_CAST")
val logic = FlowLogicRefFactoryImpl.toFlowLogic(logicRef) as FlowLogic<T>
return startFlow(logic, flowInitiator, me)
return startFlow(logic, flowInitiator, ourIdentity = null)
}
fun getFlowFactory(initiatingFlowClass: Class<out FlowLogic<*>>): InitiatedFlowFactory<*>?

View File

@ -12,9 +12,12 @@ import net.corda.core.crypto.random63BitValue
import net.corda.core.flows.*
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.*
import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.abbreviate
import net.corda.core.internal.concurrent.OpenFuture
import net.corda.core.internal.concurrent.openFuture
import net.corda.core.internal.isRegularFile
import net.corda.core.internal.staticField
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.*
import net.corda.node.services.api.FlowAppAuditEvent
@ -37,7 +40,9 @@ class FlowStateMachineImpl<R>(override val id: StateMachineRunId,
val logic: FlowLogic<R>,
scheduler: FiberScheduler,
override val flowInitiator: FlowInitiator,
override val ourIdentity: PartyAndCertificate) : Fiber<Unit>(id.toString(), scheduler), FlowStateMachine<R> {
// Store the Party rather than the full cert path with PartyAndCertificate
val ourIdentity: Party) : Fiber<Unit>(id.toString(), scheduler), FlowStateMachine<R> {
companion object {
// Used to work around a small limitation in Quasar.
private val QUASAR_UNBLOCKER = Fiber::class.staticField<Any>("SERIALIZER_BLOCKER").value
@ -67,6 +72,7 @@ class FlowStateMachineImpl<R>(override val id: StateMachineRunId,
// These fields shouldn't be serialised, so they are marked @Transient.
@Transient override lateinit var serviceHub: ServiceHubInternal
@Transient override lateinit var ourIdentityAndCert: PartyAndCertificate
@Transient internal lateinit var database: CordaPersistence
@Transient internal lateinit var actionOnSuspend: (FlowIORequest) -> Unit
@Transient internal lateinit var actionOnEnd: (Try<R>, Boolean) -> Unit

View File

@ -3,7 +3,6 @@ package net.corda.node.services.statemachine
import net.corda.core.flows.FlowException
import net.corda.core.flows.UnexpectedFlowEndException
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.castIfPossible
import net.corda.core.serialization.CordaSerializable
import net.corda.core.utilities.UntrustworthyData
@ -26,9 +25,7 @@ data class SessionInit(val initiatorSessionId: Long,
val initiatingFlowClass: String,
val flowVersion: Int,
val appName: String,
val firstPayload: Any?,
// Left as a placeholder for support of multiple identities on a node. For now we choose the first one as a special one.
val otherIdentity: PartyAndCertificate? = null) : SessionMessage
val firstPayload: Any?) : SessionMessage
data class SessionConfirm(override val initiatorSessionId: Long,
val initiatedSessionId: Long,

View File

@ -14,7 +14,6 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.random63BitValue
import net.corda.core.flows.*
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.ThreadBox
import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.internal.castIfPossible
@ -371,8 +370,9 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
session.receivedMessages += ReceivedSessionMessage(sender, SessionData(session.ourSessionId, sessionInit.firstPayload))
}
openSessions[session.ourSessionId] = session
val meIdentity = sessionInit.otherIdentity ?: serviceHub.myInfo.legalIdentitiesAndCerts.first()
val fiber = createFiber(flow, FlowInitiator.Peer(sender), meIdentity)
// TODO Perhaps the session-init will specificy which of our multiple identies to use, which we would have to
// double-check is actually ours. However, what if we want to control how our identities gets used?
val fiber = createFiber(flow, FlowInitiator.Peer(sender))
flowSession.sessionFlow = flow
flowSession.stateMachine = fiber
fiber.openSessions[Pair(flow, sender)] = session
@ -427,15 +427,23 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
}
}
private fun <T> createFiber(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate): FlowStateMachineImpl<T> {
val id = StateMachineRunId.createRandom()
return FlowStateMachineImpl(id, logic, scheduler, flowInitiator, me).apply { initFiber(this) }
private fun <T> createFiber(logic: FlowLogic<T>, flowInitiator: FlowInitiator, ourIdentity: Party? = null): FlowStateMachineImpl<T> {
val fsm = FlowStateMachineImpl(
StateMachineRunId.createRandom(),
logic,
scheduler,
flowInitiator,
ourIdentity ?: serviceHub.myInfo.legalIdentities[0])
initFiber(fsm)
return fsm
}
private fun initFiber(fiber: FlowStateMachineImpl<*>) {
verifyFlowLogicIsSuspendable(fiber.logic)
fiber.database = database
fiber.serviceHub = serviceHub
fiber.ourIdentityAndCert = serviceHub.myInfo.legalIdentitiesAndCerts.find { it.party == fiber.ourIdentity }
?: throw IllegalStateException("Identity specified by ${fiber.id} (${fiber.ourIdentity}) is not one of ours!")
fiber.actionOnSuspend = { ioRequest ->
updateCheckpoint(fiber)
// We commit on the fibers transaction that was copied across ThreadLocals during suspend
@ -514,11 +522,11 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
*
* Note that you must be on the [executor] thread.
*/
fun <T> add(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate?): FlowStateMachineImpl<T> {
fun <T> add(logic: FlowLogic<T>, flowInitiator: FlowInitiator, ourIdentity: Party? = null): FlowStateMachineImpl<T> {
// TODO: Check that logic has @Suspendable on its call method.
executor.checkOnThread()
val fiber = database.transaction {
val fiber = createFiber(logic, flowInitiator, me ?: serviceHub.myInfo.legalIdentitiesAndCerts.first())
val fiber = createFiber(logic, flowInitiator, ourIdentity)
updateCheckpoint(fiber)
fiber
}

View File

@ -545,17 +545,17 @@ class TwoPartyTradeFlowTests {
}
@InitiatingFlow
class SellerInitiator(val buyer: Party,
val notary: NodeInfo,
val assetToSell: StateAndRef<OwnableState>,
val price: Amount<Currency>,
val anonymous: Boolean) : FlowLogic<SignedTransaction>() {
class SellerInitiator(private val buyer: Party,
private val notary: NodeInfo,
private val assetToSell: StateAndRef<OwnableState>,
private val price: Amount<Currency>,
private val anonymous: Boolean) : FlowLogic<SignedTransaction>() {
@Suspendable
override fun call(): SignedTransaction {
val myParty = if (anonymous) {
serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.chooseIdentityAndCert(), false)
val myPartyAndCert = if (anonymous) {
serviceHub.keyManagementService.freshKeyAndCert(ourIdentityAndCert, false)
} else {
serviceHub.myInfo.chooseIdentityAndCert()
ourIdentityAndCert
}
send(buyer, TestTx(notary.notaryIdentity, price, anonymous))
return subFlow(Seller(
@ -563,12 +563,12 @@ class TwoPartyTradeFlowTests {
notary,
assetToSell,
price,
myParty))
myPartyAndCert))
}
}
@InitiatedBy(SellerInitiator::class)
class BuyerAcceptor(val seller: Party) : FlowLogic<SignedTransaction>() {
class BuyerAcceptor(private val seller: Party) : FlowLogic<SignedTransaction>() {
@Suspendable
override fun call(): SignedTransaction {
val (notary, price, anonymous) = receive<TestTx>(seller).unwrap {

View File

@ -37,6 +37,7 @@ class ScheduledFlowTests {
val PAGE_SIZE = 20
val SORTING = Sort(listOf(Sort.SortColumn(SortAttribute.Standard(Sort.CommonStateAttribute.STATE_REF_TXN_ID), Sort.Direction.DESC)))
}
lateinit var mockNet: MockNetwork
lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
lateinit var nodeA: StartedNode<MockNetwork.MockNode>
@ -59,23 +60,22 @@ class ScheduledFlowTests {
override val participants: List<AbstractParty> = listOf(source, destination)
}
class InsertInitialStateFlow(val destination: Party) : FlowLogic<Unit>() {
class InsertInitialStateFlow(private val destination: Party) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
val scheduledState = ScheduledState(serviceHub.clock.instant(),
serviceHub.myInfo.chooseIdentity(), destination)
val scheduledState = ScheduledState(serviceHub.clock.instant(), ourIdentity, destination)
val notary = serviceHub.networkMapCache.getAnyNotary()
val builder = TransactionBuilder(notary)
.addOutputState(scheduledState, DUMMY_PROGRAM_ID)
.addCommand(dummyCommand(ourIdentity.owningKey))
val tx = serviceHub.signInitialTransaction(builder)
subFlow(FinalityFlow(tx, setOf(serviceHub.myInfo.chooseIdentity())))
subFlow(FinalityFlow(tx, setOf(ourIdentity)))
}
}
@SchedulableFlow
class ScheduledFlow(val stateRef: StateRef) : FlowLogic<Unit>() {
class ScheduledFlow(private val stateRef: StateRef) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
val state = serviceHub.toStateAndRef<ScheduledState>(stateRef)
@ -90,7 +90,7 @@ class ScheduledFlowTests {
val builder = TransactionBuilder(notary)
.addInputState(state)
.addOutputState(newStateOutput, DUMMY_PROGRAM_ID)
.addCommand(dummyCommand(serviceHub.myInfo.chooseIdentity().owningKey))
.addCommand(dummyCommand(ourIdentity.owningKey))
val tx = serviceHub.signInitialTransaction(builder)
subFlow(FinalityFlow(tx, setOf(scheduledState.source, scheduledState.destination)))
}

View File

@ -25,7 +25,6 @@ import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.getOrThrow
import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.driver.poll
import java.io.InputStream
import java.net.HttpURLConnection
@ -118,7 +117,7 @@ class AttachmentDemoFlow(val otherSide: Party, val notary: Party, val hash: Secu
// Create a trivial transaction with an output that describes the attachment, and the attachment itself
val ptx = TransactionBuilder(notary)
.addOutputState(AttachmentContract.State(hash), ATTACHMENT_PROGRAM_ID)
.addCommand(AttachmentContract.Command, serviceHub.myInfo.chooseIdentity().owningKey)
.addCommand(AttachmentContract.Command, ourIdentity.owningKey)
.addAttachment(hash)
progressTracker.currentStep = SIGNING

View File

@ -62,7 +62,7 @@ object AutoOfferFlow {
}
private fun <T : AbstractParty> notUs(parties: List<T>): List<T> {
return parties.filter { ourIdentity.party != it }
return parties.filter { ourIdentity != it }
}
}

View File

@ -11,7 +11,6 @@ import net.corda.core.identity.Party
import net.corda.core.transactions.LedgerTransaction
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.testing.chooseIdentity
@StartableByRPC
class DummyIssueAndMove(private val notary: Party, private val counterpartyNode: Party, private val discriminator: Int) : FlowLogic<SignedTransaction>() {
@ -27,10 +26,10 @@ class DummyIssueAndMove(private val notary: Party, private val counterpartyNode:
@Suspendable
override fun call(): SignedTransaction {
// Self issue an asset
val state = State(listOf(serviceHub.myInfo.chooseIdentity()), discriminator)
val state = State(listOf(ourIdentity), discriminator)
val issueTx = serviceHub.signInitialTransaction(TransactionBuilder(notary).apply {
addOutputState(state, DO_NOTHING_PROGRAM_ID)
addCommand(DummyCommand(),listOf(serviceHub.myInfo.chooseIdentity().owningKey))
addCommand(DummyCommand(),listOf(ourIdentity.owningKey))
})
serviceHub.recordTransactions(issueTx)
// Move ownership of the asset to the counterparty
@ -38,7 +37,7 @@ class DummyIssueAndMove(private val notary: Party, private val counterpartyNode:
return serviceHub.signInitialTransaction(TransactionBuilder(notary).apply {
addInputState(issueTx.tx.outRef<ContractState>(0))
addOutputState(state.copy(participants = listOf(counterpartyNode)), DO_NOTHING_PROGRAM_ID)
addCommand(DummyCommand(),listOf(serviceHub.myInfo.chooseIdentity().owningKey))
addCommand(DummyCommand(),listOf(ourIdentity.owningKey))
})
}
}

View File

@ -11,7 +11,6 @@ import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.unwrap
import net.corda.finance.flows.TwoPartyDealFlow
import net.corda.vega.contracts.IRSState
import net.corda.vega.contracts.OGTrade
import net.corda.vega.contracts.SwapData
object IRSTradeFlow {
@ -27,9 +26,9 @@ object IRSTradeFlow {
val notary = serviceHub.networkMapCache.notaryNodes.first().notaryIdentity
val (buyer, seller) =
if (swap.buyer.second == ourIdentity.owningKey) {
Pair(ourIdentity.party, otherParty)
Pair(ourIdentity, otherParty)
} else {
Pair(otherParty, ourIdentity.party)
Pair(otherParty, ourIdentity)
}
val offer = IRSState(swap, buyer, seller)

View File

@ -21,7 +21,10 @@ import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.unwrap
import net.corda.finance.flows.TwoPartyDealFlow
import net.corda.vega.analytics.*
import net.corda.vega.contracts.*
import net.corda.vega.contracts.IRSState
import net.corda.vega.contracts.PortfolioState
import net.corda.vega.contracts.PortfolioValuation
import net.corda.vega.contracts.RevisionedState
import net.corda.vega.portfolio.Portfolio
import net.corda.vega.portfolio.toPortfolio
import java.time.LocalDate
@ -48,16 +51,16 @@ object SimmFlow {
*/
@InitiatingFlow
@StartableByRPC
class Requester(val otherParty: Party,
val valuationDate: LocalDate,
val existing: StateAndRef<PortfolioState>?)
class Requester(private val otherParty: Party,
private val valuationDate: LocalDate,
private val existing: StateAndRef<PortfolioState>?)
: FlowLogic<RevisionedState<PortfolioState.Update>>() {
constructor(otherParty: Party, valuationDate: LocalDate) : this(otherParty, valuationDate, null)
lateinit var notary: Party
@Suspendable
override fun call(): RevisionedState<PortfolioState.Update> {
logger.debug("Calling from: ${ourIdentity.party}. Sending to: $otherParty")
logger.debug("Calling from: $ourIdentity. Sending to: $otherParty")
require(serviceHub.networkMapCache.notaryNodes.isNotEmpty()) { "No notary nodes registered" }
notary = serviceHub.networkMapCache.notaryNodes.first().notaryIdentity
@ -80,7 +83,7 @@ object SimmFlow {
@Suspendable
private fun agreePortfolio(portfolio: Portfolio) {
logger.info("Agreeing portfolio")
val parties = Pair(ourIdentity.party, otherParty)
val parties = Pair(ourIdentity, otherParty)
val portfolioState = PortfolioState(portfolio.refs, parties, valuationDate)
send(otherParty, OfferMessage(notary, portfolioState, existing?.ref, valuationDate))

View File

@ -17,12 +17,12 @@ import java.time.LocalDate
object SimmRevaluation {
@StartableByRPC
@SchedulableFlow
class Initiator(val curStateRef: StateRef, val valuationDate: LocalDate) : FlowLogic<Unit>() {
class Initiator(private val curStateRef: StateRef, private val valuationDate: LocalDate) : FlowLogic<Unit>() {
@Suspendable
override fun call(): Unit {
override fun call() {
val stateAndRef = serviceHub.vaultQueryService.queryBy<PortfolioState>(VaultQueryCriteria(stateRefs = listOf(curStateRef))).states.single()
val curState = stateAndRef.state.data
if (ourIdentity.party == curState.participants[0]) {
if (ourIdentity == curState.participants[0]) {
val otherParty = serviceHub.identityService.partyFromAnonymous(curState.participants[1])
require(otherParty != null) { "Other party must be known by this node" }
subFlow(SimmFlow.Requester(otherParty!!, valuationDate, stateAndRef))

View File

@ -22,10 +22,10 @@ import java.util.*
* Flow for the Bank of Corda node to issue some commercial paper to the seller's node, to sell to the buyer.
*/
@StartableByRPC
class CommercialPaperIssueFlow(val amount: Amount<Currency>,
val issueRef: OpaqueBytes,
val recipient: Party,
val notary: Party,
class CommercialPaperIssueFlow(private val amount: Amount<Currency>,
private val issueRef: OpaqueBytes,
private val recipient: Party,
private val notary: Party,
override val progressTracker: ProgressTracker) : FlowLogic<SignedTransaction>() {
constructor(amount: Amount<Currency>, issueRef: OpaqueBytes, recipient: Party, notary: Party) : this(amount, issueRef, recipient, notary, tracker())
@ -40,7 +40,7 @@ class CommercialPaperIssueFlow(val amount: Amount<Currency>,
progressTracker.currentStep = ISSUING
val issuance: SignedTransaction = run {
val tx = CommercialPaper().generateIssue(ourIdentity.party.ref(issueRef), amount `issued by` ourIdentity.party.ref(issueRef),
val tx = CommercialPaper().generateIssue(ourIdentity.ref(issueRef), amount `issued by` ourIdentity.ref(issueRef),
Instant.now() + 10.days, notary)
// TODO: Consider moving these two steps below into generateIssue.

View File

@ -16,8 +16,8 @@ import java.util.*
@InitiatingFlow
@StartableByRPC
class SellerFlow(val otherParty: Party,
val amount: Amount<Currency>,
class SellerFlow(private val otherParty: Party,
private val amount: Amount<Currency>,
override val progressTracker: ProgressTracker) : FlowLogic<SignedTransaction>() {
constructor(otherParty: Party, amount: Amount<Currency>) : this(otherParty, amount, tracker())
@ -41,7 +41,7 @@ class SellerFlow(val otherParty: Party,
progressTracker.currentStep = SELF_ISSUING
val notary: NodeInfo = serviceHub.networkMapCache.notaryNodes[0]
val cpOwner = serviceHub.keyManagementService.freshKeyAndCert(ourIdentity, false)
val cpOwner = serviceHub.keyManagementService.freshKeyAndCert(ourIdentityAndCert, false)
val commercialPaper = serviceHub.vaultQueryService.queryBy(CommercialPaper.State::class.java).states.first()
progressTracker.currentStep = TRADING

View File

@ -3,11 +3,10 @@ package net.corda.node.testing
import com.codahale.metrics.MetricRegistry
import net.corda.core.flows.FlowInitiator
import net.corda.core.flows.FlowLogic
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.identity.Party
import net.corda.core.node.NodeInfo
import net.corda.core.node.services.*
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.utilities.NonEmptySet
import net.corda.node.internal.InitiatedFlowFactory
import net.corda.node.serialization.NodeClock
import net.corda.node.services.api.*
@ -79,9 +78,8 @@ open class MockServiceHubInternal(
override fun <T : SerializeAsToken> cordaService(type: Class<T>): T = throw UnsupportedOperationException()
override fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate?): FlowStateMachineImpl<T> {
check(me == null || me in myInfo.legalIdentitiesAndCerts) { "Attempt to start a flow with legal identity not belonging to this node." }
return smm.executor.fetchFrom { smm.add(logic, flowInitiator, me) }
override fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator, ourIdentity: Party?): FlowStateMachineImpl<T> {
return smm.executor.fetchFrom { smm.add(logic, flowInitiator, ourIdentity) }
}
override fun getFlowFactory(initiatingFlowClass: Class<out FlowLogic<*>>): InitiatedFlowFactory<*>? = null

View File

@ -12,7 +12,9 @@ import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.cert
import net.corda.core.node.NodeInfo
import net.corda.core.node.services.IdentityService
import net.corda.core.utilities.*
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.loggerFor
import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER
import net.corda.node.services.config.configureDevKeyAndTrustStores
import net.corda.node.services.identity.InMemoryIdentityService
@ -159,4 +161,4 @@ inline fun <reified T : Any> amqpSpecific(reason: String, function: () -> Unit)
* TODO: Should be removed after multiple identities are introduced.
*/
fun NodeInfo.chooseIdentityAndCert(): PartyAndCertificate = legalIdentitiesAndCerts.first()
fun NodeInfo.chooseIdentity(): Party = legalIdentitiesAndCerts.first().party
fun NodeInfo.chooseIdentity(): Party = chooseIdentityAndCert().party