CORDA-939 - Dont expose FlowStateMachine via public API (#2438) (#2476)

* CORDA-939 - Dont expose FlowStateMachine via public API (#2438)

* Create CordaInternal attribute for properties on public classes that are not part of the api and apply to FlowLogic.stateMachine

* Remove startFlow from public test api and replace with startFlowAndReturnFuture

* Update api-current with changed signature

* Change test used in documentation to use public test methods

* Remove the rest of the unneccessary usages of the startFlow test utility

* Remove extra whitespace

* Rename startFlowAndReturnFuture back to startFlow

* Update api

* The annotation doesn't appear unless its marked as on the actual getter and setter

* Updated docs and removed pointless attribute

* Deleted whitespace

# Conflicts:
#	.ci/api-current.txt
#	testing/node-driver/src/main/kotlin/net/corda/testing/node/NodeTestUtils.kt

* Revert api-current to v1 api

* Adding missing line and missing annotations

* Made changes post review

* Minor text change
This commit is contained in:
Anthony Keenan 2018-02-08 14:40:16 +00:00 committed by Katelyn Baker
parent 9c2b5f4ced
commit e41408d21e
38 changed files with 122 additions and 100 deletions

View File

@ -1216,7 +1216,7 @@ public abstract class net.corda.core.flows.FlowLogic extends java.lang.Object
@org.jetbrains.annotations.Nullable public net.corda.core.utilities.ProgressTracker getProgressTracker() @org.jetbrains.annotations.Nullable public net.corda.core.utilities.ProgressTracker getProgressTracker()
@org.jetbrains.annotations.NotNull public final net.corda.core.flows.StateMachineRunId getRunId() @org.jetbrains.annotations.NotNull public final net.corda.core.flows.StateMachineRunId getRunId()
@org.jetbrains.annotations.NotNull public final net.corda.core.node.ServiceHub getServiceHub() @org.jetbrains.annotations.NotNull public final net.corda.core.node.ServiceHub getServiceHub()
@org.jetbrains.annotations.NotNull public final net.corda.core.internal.FlowStateMachine getStateMachine() @net.corda.core.CordaInternal @org.jetbrains.annotations.NotNull public final net.corda.core.internal.FlowStateMachine getStateMachine()
@co.paralleluniverse.fibers.Suspendable @org.jetbrains.annotations.NotNull public final net.corda.core.flows.FlowSession initiateFlow(net.corda.core.identity.Party) @co.paralleluniverse.fibers.Suspendable @org.jetbrains.annotations.NotNull public final net.corda.core.flows.FlowSession initiateFlow(net.corda.core.identity.Party)
@co.paralleluniverse.fibers.Suspendable public final void persistFlowStackSnapshot() @co.paralleluniverse.fibers.Suspendable public final void persistFlowStackSnapshot()
@kotlin.Deprecated @co.paralleluniverse.fibers.Suspendable @org.jetbrains.annotations.NotNull public net.corda.core.utilities.UntrustworthyData receive(Class, net.corda.core.identity.Party) @kotlin.Deprecated @co.paralleluniverse.fibers.Suspendable @org.jetbrains.annotations.NotNull public net.corda.core.utilities.UntrustworthyData receive(Class, net.corda.core.identity.Party)
@ -1225,7 +1225,7 @@ public abstract class net.corda.core.flows.FlowLogic extends java.lang.Object
public final void recordAuditEvent(String, String, Map) public final void recordAuditEvent(String, String, Map)
@kotlin.Deprecated @co.paralleluniverse.fibers.Suspendable public void send(net.corda.core.identity.Party, Object) @kotlin.Deprecated @co.paralleluniverse.fibers.Suspendable public void send(net.corda.core.identity.Party, Object)
@kotlin.Deprecated @co.paralleluniverse.fibers.Suspendable @org.jetbrains.annotations.NotNull public net.corda.core.utilities.UntrustworthyData sendAndReceive(Class, net.corda.core.identity.Party, Object) @kotlin.Deprecated @co.paralleluniverse.fibers.Suspendable @org.jetbrains.annotations.NotNull public net.corda.core.utilities.UntrustworthyData sendAndReceive(Class, net.corda.core.identity.Party, Object)
public final void setStateMachine(net.corda.core.internal.FlowStateMachine) @net.corda.core.CordaInternal public final void setStateMachine(net.corda.core.internal.FlowStateMachine)
@co.paralleluniverse.fibers.Suspendable @kotlin.jvm.JvmStatic public static final void sleep(java.time.Duration) @co.paralleluniverse.fibers.Suspendable @kotlin.jvm.JvmStatic public static final void sleep(java.time.Duration)
@co.paralleluniverse.fibers.Suspendable public Object subFlow(net.corda.core.flows.FlowLogic) @co.paralleluniverse.fibers.Suspendable public Object subFlow(net.corda.core.flows.FlowLogic)
@org.jetbrains.annotations.Nullable public final net.corda.core.messaging.DataFeed track() @org.jetbrains.annotations.Nullable public final net.corda.core.messaging.DataFeed track()

View File

@ -58,12 +58,12 @@ class IdentitySyncFlowTests {
val anonymous = true val anonymous = true
val ref = OpaqueBytes.of(0x01) val ref = OpaqueBytes.of(0x01)
val issueFlow = aliceNode.services.startFlow(CashIssueAndPaymentFlow(1000.DOLLARS, ref, alice, anonymous, notary)) val issueFlow = aliceNode.services.startFlow(CashIssueAndPaymentFlow(1000.DOLLARS, ref, alice, anonymous, notary))
val issueTx = issueFlow.resultFuture.getOrThrow().stx val issueTx = issueFlow.getOrThrow().stx
val confidentialIdentity = issueTx.tx.outputs.map { it.data }.filterIsInstance<Cash.State>().single().owner val confidentialIdentity = issueTx.tx.outputs.map { it.data }.filterIsInstance<Cash.State>().single().owner
assertNull(bobNode.database.transaction { bobNode.services.identityService.wellKnownPartyFromAnonymous(confidentialIdentity) }) assertNull(bobNode.database.transaction { bobNode.services.identityService.wellKnownPartyFromAnonymous(confidentialIdentity) })
// Run the flow to sync up the identities // Run the flow to sync up the identities
aliceNode.services.startFlow(Initiator(bob, issueTx.tx)).resultFuture.getOrThrow() aliceNode.services.startFlow(Initiator(bob, issueTx.tx)).getOrThrow()
val expected = aliceNode.database.transaction { val expected = aliceNode.database.transaction {
aliceNode.services.identityService.wellKnownPartyFromAnonymous(confidentialIdentity) aliceNode.services.identityService.wellKnownPartyFromAnonymous(confidentialIdentity)
} }
@ -88,7 +88,7 @@ class IdentitySyncFlowTests {
val anonymous = true val anonymous = true
val ref = OpaqueBytes.of(0x01) val ref = OpaqueBytes.of(0x01)
val issueFlow = charlieNode.services.startFlow(CashIssueAndPaymentFlow(1000.DOLLARS, ref, charlie, anonymous, notary)) val issueFlow = charlieNode.services.startFlow(CashIssueAndPaymentFlow(1000.DOLLARS, ref, charlie, anonymous, notary))
val issueTx = issueFlow.resultFuture.getOrThrow().stx val issueTx = issueFlow.getOrThrow().stx
val confidentialIdentity = issueTx.tx.outputs.map { it.data }.filterIsInstance<Cash.State>().single().owner val confidentialIdentity = issueTx.tx.outputs.map { it.data }.filterIsInstance<Cash.State>().single().owner
val confidentialIdentCert = charlieNode.services.identityService.certificateFromKey(confidentialIdentity.owningKey)!! val confidentialIdentCert = charlieNode.services.identityService.certificateFromKey(confidentialIdentity.owningKey)!!
@ -97,11 +97,11 @@ class IdentitySyncFlowTests {
assertNotNull(aliceNode.database.transaction { aliceNode.services.identityService.wellKnownPartyFromAnonymous(confidentialIdentity) }) assertNotNull(aliceNode.database.transaction { aliceNode.services.identityService.wellKnownPartyFromAnonymous(confidentialIdentity) })
// Generate a payment from Charlie to Alice, including the confidential state // Generate a payment from Charlie to Alice, including the confidential state
val payTx = charlieNode.services.startFlow(CashPaymentFlow(1000.DOLLARS, alice, anonymous)).resultFuture.getOrThrow().stx val payTx = charlieNode.services.startFlow(CashPaymentFlow(1000.DOLLARS, alice, anonymous)).getOrThrow().stx
// Run the flow to sync up the identities, and confirm Charlie's confidential identity doesn't leak // Run the flow to sync up the identities, and confirm Charlie's confidential identity doesn't leak
assertNull(bobNode.database.transaction { bobNode.services.identityService.wellKnownPartyFromAnonymous(confidentialIdentity) }) assertNull(bobNode.database.transaction { bobNode.services.identityService.wellKnownPartyFromAnonymous(confidentialIdentity) })
aliceNode.services.startFlow(Initiator(bob, payTx.tx)).resultFuture.getOrThrow() aliceNode.services.startFlow(Initiator(bob, payTx.tx)).getOrThrow()
assertNull(bobNode.database.transaction { bobNode.services.identityService.wellKnownPartyFromAnonymous(confidentialIdentity) }) assertNull(bobNode.database.transaction { bobNode.services.identityService.wellKnownPartyFromAnonymous(confidentialIdentity) })
} }

View File

@ -30,7 +30,7 @@ class SwapIdentitiesFlowTests {
val requesterFlow = aliceNode.services.startFlow(SwapIdentitiesFlow(bob)) val requesterFlow = aliceNode.services.startFlow(SwapIdentitiesFlow(bob))
// Get the results // Get the results
val actual: Map<Party, AnonymousParty> = requesterFlow.resultFuture.getOrThrow().toMap() val actual: Map<Party, AnonymousParty> = requesterFlow.getOrThrow().toMap()
assertEquals(2, actual.size) assertEquals(2, actual.size)
// Verify that the generated anonymous identities do not match the well known identities // Verify that the generated anonymous identities do not match the well known identities
val aliceAnonymousIdentity = actual[alice] ?: throw IllegalStateException() val aliceAnonymousIdentity = actual[alice] ?: throw IllegalStateException()

View File

@ -0,0 +1,11 @@
package net.corda.core
/**
* These methods are not part of Corda's API compatibility guarantee and applications should not use them.
*
* These fields are only meant to be used by Corda internally, and are not intended to be part of the public API.
*/
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@MustBeDocumented
annotation class CordaInternal

View File

@ -2,6 +2,7 @@ package net.corda.core.flows
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import co.paralleluniverse.strands.Strand import co.paralleluniverse.strands.Strand
import net.corda.core.CordaInternal
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate import net.corda.core.identity.PartyAndCertificate
@ -418,7 +419,9 @@ abstract class FlowLogic<out T> {
* is public only because it must be accessed across module boundaries. * is public only because it must be accessed across module boundaries.
*/ */
var stateMachine: FlowStateMachine<*> var stateMachine: FlowStateMachine<*>
@CordaInternal
get() = _stateMachine ?: throw IllegalStateException("This can only be done after the flow has been started.") get() = _stateMachine ?: throw IllegalStateException("This can only be done after the flow has been started.")
@CordaInternal
set(value) { set(value) {
_stateMachine = value _stateMachine = value
} }

View File

@ -40,7 +40,7 @@ public class FlowsInJavaTest {
@Test @Test
public void suspendableActionInsideUnwrap() throws Exception { public void suspendableActionInsideUnwrap() throws Exception {
bobNode.registerInitiatedFlow(SendHelloAndThenReceive.class); bobNode.registerInitiatedFlow(SendHelloAndThenReceive.class);
Future<String> result = startFlow(aliceNode.getServices(), new SendInUnwrapFlow(bob)).getResultFuture(); Future<String> result = startFlow(aliceNode.getServices(), new SendInUnwrapFlow(bob));
mockNet.runNetwork(); mockNet.runNetwork();
assertThat(result.get()).isEqualTo("Hello"); assertThat(result.get()).isEqualTo("Hello");
} }
@ -56,7 +56,7 @@ public class FlowsInJavaTest {
private void primitiveReceiveTypeTest(Class<?> receiveType) throws InterruptedException { private void primitiveReceiveTypeTest(Class<?> receiveType) throws InterruptedException {
PrimitiveReceiveFlow flow = new PrimitiveReceiveFlow(bob, receiveType); PrimitiveReceiveFlow flow = new PrimitiveReceiveFlow(bob, receiveType);
Future<?> result = startFlow(aliceNode.getServices(), flow).getResultFuture(); Future<?> result = startFlow(aliceNode.getServices(), flow);
mockNet.runNetwork(); mockNet.runNetwork();
try { try {
result.get(); result.get();

View File

@ -65,7 +65,7 @@ class AttachmentTests {
mockNet.runNetwork() mockNet.runNetwork()
val bobFlow = bobNode.startAttachmentFlow(setOf(id), alice) val bobFlow = bobNode.startAttachmentFlow(setOf(id), alice)
mockNet.runNetwork() mockNet.runNetwork()
assertEquals(0, bobFlow.resultFuture.getOrThrow().fromDisk.size) assertEquals(0, bobFlow.getOrThrow().fromDisk.size)
// Verify it was inserted into node one's store. // Verify it was inserted into node one's store.
val attachment = bobNode.database.transaction { val attachment = bobNode.database.transaction {
@ -77,7 +77,7 @@ class AttachmentTests {
// Shut down node zero and ensure node one can still resolve the attachment. // Shut down node zero and ensure node one can still resolve the attachment.
aliceNode.dispose() aliceNode.dispose()
val response: FetchDataFlow.Result<Attachment> = bobNode.startAttachmentFlow(setOf(id), alice).resultFuture.getOrThrow() val response: FetchDataFlow.Result<Attachment> = bobNode.startAttachmentFlow(setOf(id), alice).getOrThrow()
assertEquals(attachment, response.fromDisk[0]) assertEquals(attachment, response.fromDisk[0])
} }
@ -92,7 +92,7 @@ class AttachmentTests {
val alice = aliceNode.info.singleIdentity() val alice = aliceNode.info.singleIdentity()
val bobFlow = bobNode.startAttachmentFlow(setOf(hash), alice) val bobFlow = bobNode.startAttachmentFlow(setOf(hash), alice)
mockNet.runNetwork() mockNet.runNetwork()
val e = assertFailsWith<FetchDataFlow.HashNotFound> { bobFlow.resultFuture.getOrThrow() } val e = assertFailsWith<FetchDataFlow.HashNotFound> { bobFlow.getOrThrow() }
assertEquals(hash, e.requested) assertEquals(hash, e.requested)
} }
@ -127,7 +127,7 @@ class AttachmentTests {
mockNet.runNetwork() mockNet.runNetwork()
val bobFlow = bobNode.startAttachmentFlow(setOf(id), alice) val bobFlow = bobNode.startAttachmentFlow(setOf(id), alice)
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith<FetchDataFlow.DownloadedVsRequestedDataMismatch> { bobFlow.resultFuture.getOrThrow() } assertFailsWith<FetchDataFlow.DownloadedVsRequestedDataMismatch> { bobFlow.getOrThrow() }
} }
private fun StartedNode<*>.startAttachmentFlow(hashes: Set<SecureHash>, otherSide: Party) = services.startFlow(InitiatingFetchAttachmentsFlow(otherSide, hashes)) private fun StartedNode<*>.startAttachmentFlow(hashes: Set<SecureHash>, otherSide: Party) = services.startFlow(InitiatingFetchAttachmentsFlow(otherSide, hashes))

View File

@ -115,7 +115,7 @@ class CollectSignaturesFlowTests {
val state = DummyContract.MultiOwnerState(magicNumber, parties) val state = DummyContract.MultiOwnerState(magicNumber, parties)
val flow = aliceNode.services.startFlow(TestFlow.Initiator(state, notary)) val flow = aliceNode.services.startFlow(TestFlow.Initiator(state, notary))
mockNet.runNetwork() mockNet.runNetwork()
val result = flow.resultFuture.getOrThrow() val result = flow.getOrThrow()
result.verifyRequiredSignatures() result.verifyRequiredSignatures()
println(result.tx) println(result.tx)
println(result.sigs) println(result.sigs)
@ -127,7 +127,7 @@ class CollectSignaturesFlowTests {
val ptx = aliceNode.services.signInitialTransaction(onePartyDummyContract) val ptx = aliceNode.services.signInitialTransaction(onePartyDummyContract)
val flow = aliceNode.services.startFlow(CollectSignaturesFlow(ptx, emptySet())) val flow = aliceNode.services.startFlow(CollectSignaturesFlow(ptx, emptySet()))
mockNet.runNetwork() mockNet.runNetwork()
val result = flow.resultFuture.getOrThrow() val result = flow.getOrThrow()
result.verifyRequiredSignatures() result.verifyRequiredSignatures()
println(result.tx) println(result.tx)
println(result.sigs) println(result.sigs)
@ -141,7 +141,7 @@ class CollectSignaturesFlowTests {
val flow = aliceNode.services.startFlow(CollectSignaturesFlow(ptx, emptySet())) val flow = aliceNode.services.startFlow(CollectSignaturesFlow(ptx, emptySet()))
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith<IllegalArgumentException>("The Initiator of CollectSignaturesFlow must have signed the transaction.") { assertFailsWith<IllegalArgumentException>("The Initiator of CollectSignaturesFlow must have signed the transaction.") {
flow.resultFuture.getOrThrow() flow.getOrThrow()
} }
} }
@ -155,7 +155,7 @@ class CollectSignaturesFlowTests {
val signedByBoth = bobNode.services.addSignature(signedByA) val signedByBoth = bobNode.services.addSignature(signedByA)
val flow = aliceNode.services.startFlow(CollectSignaturesFlow(signedByBoth, emptySet())) val flow = aliceNode.services.startFlow(CollectSignaturesFlow(signedByBoth, emptySet()))
mockNet.runNetwork() mockNet.runNetwork()
val result = flow.resultFuture.getOrThrow() val result = flow.getOrThrow()
println(result.tx) println(result.tx)
println(result.sigs) println(result.sigs)
} }

View File

@ -81,24 +81,24 @@ class ContractUpgradeFlowTest {
requireNotNull(btx) requireNotNull(btx)
// The request is expected to be rejected because party B hasn't authorised the upgrade yet. // The request is expected to be rejected because party B hasn't authorised the upgrade yet.
val rejectedFuture = aliceNode.services.startFlow(ContractUpgradeFlow.Initiate(atx!!.tx.outRef(0), DummyContractV2::class.java)).resultFuture val rejectedFuture = aliceNode.services.startFlow(ContractUpgradeFlow.Initiate(atx!!.tx.outRef(0), DummyContractV2::class.java))
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith(UnexpectedFlowEndException::class) { rejectedFuture.getOrThrow() } assertFailsWith(UnexpectedFlowEndException::class) { rejectedFuture.getOrThrow() }
// Party B authorise the contract state upgrade, and immediately deauthorise the same. // Party B authorise the contract state upgrade, and immediately deauthorise the same.
bobNode.services.startFlow(ContractUpgradeFlow.Authorise(btx!!.tx.outRef<ContractState>(0), DummyContractV2::class.java)).resultFuture.getOrThrow() bobNode.services.startFlow(ContractUpgradeFlow.Authorise(btx!!.tx.outRef<ContractState>(0), DummyContractV2::class.java)).getOrThrow()
bobNode.services.startFlow(ContractUpgradeFlow.Deauthorise(btx.tx.outRef<ContractState>(0).ref)).resultFuture.getOrThrow() bobNode.services.startFlow(ContractUpgradeFlow.Deauthorise(btx.tx.outRef<ContractState>(0).ref)).getOrThrow()
// The request is expected to be rejected because party B has subsequently deauthorised and a previously authorised upgrade. // The request is expected to be rejected because party B has subsequently deauthorised and a previously authorised upgrade.
val deauthorisedFuture = aliceNode.services.startFlow(ContractUpgradeFlow.Initiate(atx.tx.outRef(0), DummyContractV2::class.java)).resultFuture val deauthorisedFuture = aliceNode.services.startFlow(ContractUpgradeFlow.Initiate(atx.tx.outRef(0), DummyContractV2::class.java))
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith(UnexpectedFlowEndException::class) { deauthorisedFuture.getOrThrow() } assertFailsWith(UnexpectedFlowEndException::class) { deauthorisedFuture.getOrThrow() }
// Party B authorise the contract state upgrade // Party B authorise the contract state upgrade
bobNode.services.startFlow(ContractUpgradeFlow.Authorise(btx.tx.outRef<ContractState>(0), DummyContractV2::class.java)).resultFuture.getOrThrow() bobNode.services.startFlow(ContractUpgradeFlow.Authorise(btx.tx.outRef<ContractState>(0), DummyContractV2::class.java)).getOrThrow()
// Party A initiates contract upgrade flow, expected to succeed this time. // Party A initiates contract upgrade flow, expected to succeed this time.
val resultFuture = aliceNode.services.startFlow(ContractUpgradeFlow.Initiate(atx.tx.outRef(0), DummyContractV2::class.java)).resultFuture val resultFuture = aliceNode.services.startFlow(ContractUpgradeFlow.Initiate(atx.tx.outRef(0), DummyContractV2::class.java))
mockNet.runNetwork() mockNet.runNetwork()
val result = resultFuture.getOrThrow() val result = resultFuture.getOrThrow()
@ -213,7 +213,7 @@ class ContractUpgradeFlowTest {
fun `upgrade Cash to v2`() { fun `upgrade Cash to v2`() {
// Create some cash. // Create some cash.
val chosenIdentity = alice val chosenIdentity = alice
val result = aliceNode.services.startFlow(CashIssueFlow(Amount(1000, USD), OpaqueBytes.of(1), notary)).resultFuture val result = aliceNode.services.startFlow(CashIssueFlow(Amount(1000, USD), OpaqueBytes.of(1), notary))
mockNet.runNetwork() mockNet.runNetwork()
val stx = result.getOrThrow().stx val stx = result.getOrThrow().stx
val anonymisedRecipient = result.get().recipient!! val anonymisedRecipient = result.get().recipient!!
@ -221,7 +221,7 @@ class ContractUpgradeFlowTest {
val baseState = aliceNode.database.transaction { aliceNode.services.vaultService.queryBy<ContractState>().states.single() } val baseState = aliceNode.database.transaction { aliceNode.services.vaultService.queryBy<ContractState>().states.single() }
assertTrue(baseState.state.data is Cash.State, "Contract state is old version.") assertTrue(baseState.state.data is Cash.State, "Contract state is old version.")
// Starts contract upgrade flow. // Starts contract upgrade flow.
val upgradeResult = aliceNode.services.startFlow(ContractUpgradeFlow.Initiate(stateAndRef, CashV2::class.java)).resultFuture val upgradeResult = aliceNode.services.startFlow(ContractUpgradeFlow.Initiate(stateAndRef, CashV2::class.java))
mockNet.runNetwork() mockNet.runNetwork()
upgradeResult.getOrThrow() upgradeResult.getOrThrow()
// Get contract state from the vault. // Get contract state from the vault.

View File

@ -53,7 +53,7 @@ class FinalityFlowTests {
val stx = aliceServices.signInitialTransaction(builder) val stx = aliceServices.signInitialTransaction(builder)
val flow = aliceServices.startFlow(FinalityFlow(stx)) val flow = aliceServices.startFlow(FinalityFlow(stx))
mockNet.runNetwork() mockNet.runNetwork()
val notarisedTx = flow.resultFuture.getOrThrow() val notarisedTx = flow.getOrThrow()
notarisedTx.verifyRequiredSignatures() notarisedTx.verifyRequiredSignatures()
val transactionSeenByB = bobServices.database.transaction { val transactionSeenByB = bobServices.database.transaction {
bobServices.validatedTransactions.getTransaction(notarisedTx.id) bobServices.validatedTransactions.getTransaction(notarisedTx.id)
@ -71,7 +71,7 @@ class FinalityFlowTests {
val flow = aliceServices.startFlow(FinalityFlow(stx)) val flow = aliceServices.startFlow(FinalityFlow(stx))
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith<IllegalArgumentException> { assertFailsWith<IllegalArgumentException> {
flow.resultFuture.getOrThrow() flow.getOrThrow()
} }
} }
} }

View File

@ -52,7 +52,7 @@ class ReceiveMultipleFlowTests {
val flow = nodes[0].services.startFlow(initiatingFlow) val flow = nodes[0].services.startFlow(initiatingFlow)
mockNet.runNetwork() mockNet.runNetwork()
val receivedAnswer = flow.resultFuture.getOrThrow() val receivedAnswer = flow.getOrThrow()
assertThat(receivedAnswer).isEqualTo(answer) assertThat(receivedAnswer).isEqualTo(answer)
} }
@ -64,7 +64,7 @@ class ReceiveMultipleFlowTests {
nodes[2].registerAnswer(AlgorithmDefinition::class, stringValue) nodes[2].registerAnswer(AlgorithmDefinition::class, stringValue)
val flow = nodes[0].services.startFlow(ParallelAlgorithmMap(nodes[1].info.singleIdentity(), nodes[2].info.singleIdentity())) val flow = nodes[0].services.startFlow(ParallelAlgorithmMap(nodes[1].info.singleIdentity(), nodes[2].info.singleIdentity()))
mockNet.runNetwork() mockNet.runNetwork()
val result = flow.resultFuture.getOrThrow() val result = flow.getOrThrow()
assertThat(result).isEqualTo(doubleValue * stringValue.length) assertThat(result).isEqualTo(doubleValue * stringValue.length)
} }
@ -76,7 +76,7 @@ class ReceiveMultipleFlowTests {
nodes[2].registerAnswer(ParallelAlgorithmList::class, value2) nodes[2].registerAnswer(ParallelAlgorithmList::class, value2)
val flow = nodes[0].services.startFlow(ParallelAlgorithmList(nodes[1].info.singleIdentity(), nodes[2].info.singleIdentity())) val flow = nodes[0].services.startFlow(ParallelAlgorithmList(nodes[1].info.singleIdentity(), nodes[2].info.singleIdentity()))
mockNet.runNetwork() mockNet.runNetwork()
val data = flow.resultFuture.getOrThrow() val data = flow.getOrThrow()
assertThat(data[0]).isEqualTo(value1) assertThat(data[0]).isEqualTo(value1)
assertThat(data[1]).isEqualTo(value2) assertThat(data[1]).isEqualTo(value2)
assertThat(data.fold(1.0) { a, b -> a * b }).isEqualTo(value1 * value2) assertThat(data.fold(1.0) { a, b -> a * b }).isEqualTo(value1 * value2)

View File

@ -52,14 +52,14 @@ class ResolveTransactionsFlowTest {
fun tearDown() { fun tearDown() {
mockNet.stopNodes() mockNet.stopNodes()
} }
// DOCEND 3 // DOCEND 3
// DOCSTART 1 // DOCSTART 1
@Test @Test
fun `resolve from two hashes`() { fun `resolve from two hashes`() {
val (stx1, stx2) = makeTransactions() val (stx1, stx2) = makeTransactions()
val p = TestFlow(setOf(stx2.id), megaCorp) val p = TestFlow(setOf(stx2.id), megaCorp)
val future = miniCorpNode.services.startFlow(p).resultFuture val future = miniCorpNode.services.startFlow(p)
mockNet.runNetwork() mockNet.runNetwork()
val results = future.getOrThrow() val results = future.getOrThrow()
assertEquals(listOf(stx1.id, stx2.id), results.map { it.id }) assertEquals(listOf(stx1.id, stx2.id), results.map { it.id })
@ -74,7 +74,7 @@ class ResolveTransactionsFlowTest {
fun `dependency with an error`() { fun `dependency with an error`() {
val stx = makeTransactions(signFirstTX = false).second val stx = makeTransactions(signFirstTX = false).second
val p = TestFlow(setOf(stx.id), megaCorp) val p = TestFlow(setOf(stx.id), megaCorp)
val future = miniCorpNode.services.startFlow(p).resultFuture val future = miniCorpNode.services.startFlow(p)
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith(SignedTransaction.SignaturesMissingException::class) { future.getOrThrow() } assertFailsWith(SignedTransaction.SignaturesMissingException::class) { future.getOrThrow() }
} }
@ -83,7 +83,7 @@ class ResolveTransactionsFlowTest {
fun `resolve from a signed transaction`() { fun `resolve from a signed transaction`() {
val (stx1, stx2) = makeTransactions() val (stx1, stx2) = makeTransactions()
val p = TestFlow(stx2, megaCorp) val p = TestFlow(stx2, megaCorp)
val future = miniCorpNode.services.startFlow(p).resultFuture val future = miniCorpNode.services.startFlow(p)
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() future.getOrThrow()
miniCorpNode.database.transaction { miniCorpNode.database.transaction {
@ -108,7 +108,7 @@ class ResolveTransactionsFlowTest {
cursor = stx cursor = stx
} }
val p = TestFlow(setOf(cursor.id), megaCorp, 40) val p = TestFlow(setOf(cursor.id), megaCorp, 40)
val future = miniCorpNode.services.startFlow(p).resultFuture val future = miniCorpNode.services.startFlow(p)
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith<ResolveTransactionsFlow.ExcessivelyLargeTransactionGraph> { future.getOrThrow() } assertFailsWith<ResolveTransactionsFlow.ExcessivelyLargeTransactionGraph> { future.getOrThrow() }
} }
@ -132,7 +132,7 @@ class ResolveTransactionsFlowTest {
} }
val p = TestFlow(setOf(stx3.id), megaCorp) val p = TestFlow(setOf(stx3.id), megaCorp)
val future = miniCorpNode.services.startFlow(p).resultFuture val future = miniCorpNode.services.startFlow(p)
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() future.getOrThrow()
} }
@ -154,7 +154,7 @@ class ResolveTransactionsFlowTest {
} }
val stx2 = makeTransactions(withAttachment = id).second val stx2 = makeTransactions(withAttachment = id).second
val p = TestFlow(stx2, megaCorp) val p = TestFlow(stx2, megaCorp)
val future = miniCorpNode.services.startFlow(p).resultFuture val future = miniCorpNode.services.startFlow(p)
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() future.getOrThrow()

View File

@ -170,6 +170,14 @@ UNRELEASED
* Move to a message based control of peer to peer bridge formation to allow for future out of process bridging components. * Move to a message based control of peer to peer bridge formation to allow for future out of process bridging components.
This removes the legacy Artemis bridges completely, so the ``useAMQPBridges`` configuration property has been removed. This removes the legacy Artemis bridges completely, so the ``useAMQPBridges`` configuration property has been removed.
* A ``CordaInternal`` attribute has been added to identify properties that are not intended to form part of the
public api and as such are not intended for public use. This is alongside the existing ``DoNotImplement`` attribute for classes which
provide Corda functionality to user applications, but should not be implemented by consumers, and any classes which
are defined in ``.internal`` packages, which are also not for public use.
* Marked ``stateMachine`` on ``FlowLogic`` as ``CordaInternal`` to make clear that is it not part of the public api and is
only for internal use
.. _changelog_v1: .. _changelog_v1:
Release 1.0 Release 1.0

View File

@ -15,11 +15,7 @@ import net.corda.core.utilities.unwrap
import net.corda.node.internal.StartedNode import net.corda.node.internal.StartedNode
import net.corda.node.services.messaging.Message import net.corda.node.services.messaging.Message
import net.corda.node.services.statemachine.SessionData import net.corda.node.services.statemachine.SessionData
import net.corda.testing.node.InMemoryMessagingNetwork import net.corda.testing.node.*
import net.corda.testing.node.MessagingServiceSpy
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.setMessagingServiceSpy
import net.corda.testing.node.startFlow
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
@ -102,6 +98,6 @@ class TutorialMockNetwork {
expectedEx.expect(IllegalArgumentException::class.java) expectedEx.expect(IllegalArgumentException::class.java)
expectedEx.expectMessage("Expected to receive 1") expectedEx.expectMessage("Expected to receive 1")
initiatingReceiveFlow.resultFuture.getOrThrow() initiatingReceiveFlow.getOrThrow()
} }
} }

View File

@ -60,7 +60,7 @@ class CustomVaultQueryTest {
OpaqueBytes.of(0x01), OpaqueBytes.of(0x01),
notary)) notary))
// Wait for the flow to stop and print // Wait for the flow to stop and print
flowHandle1.resultFuture.getOrThrow() flowHandle1.getOrThrow()
} }
private fun topUpCurrencies() { private fun topUpCurrencies() {
@ -69,7 +69,7 @@ class CustomVaultQueryTest {
OpaqueBytes.of(0x01), OpaqueBytes.of(0x01),
nodeA.info.chooseIdentity(), nodeA.info.chooseIdentity(),
notary)) notary))
flowHandle1.resultFuture.getOrThrow() flowHandle1.getOrThrow()
} }
private fun getBalances(): Pair<Map<Currency, Amount<Currency>>, Map<Currency, Amount<Currency>>> { private fun getBalances(): Pair<Map<Currency, Amount<Currency>>, Map<Currency, Amount<Currency>>> {

View File

@ -43,7 +43,7 @@ class FxTransactionBuildTutorialTest {
OpaqueBytes.of(0x01), OpaqueBytes.of(0x01),
notary)) notary))
// Wait for the flow to stop and print // Wait for the flow to stop and print
flowHandle1.resultFuture.getOrThrow() flowHandle1.getOrThrow()
printBalances() printBalances()
// Using NodeB as Issuer create some pounds. // Using NodeB as Issuer create some pounds.
@ -51,7 +51,7 @@ class FxTransactionBuildTutorialTest {
OpaqueBytes.of(0x01), OpaqueBytes.of(0x01),
notary)) notary))
// Wait for flow to come to an end and print // Wait for flow to come to an end and print
flowHandle2.resultFuture.getOrThrow() flowHandle2.getOrThrow()
printBalances() printBalances()
// Setup some futures on the vaults to await the arrival of the exchanged funds at both nodes // Setup some futures on the vaults to await the arrival of the exchanged funds at both nodes
@ -65,7 +65,7 @@ class FxTransactionBuildTutorialTest {
nodeB.info.chooseIdentity(), nodeB.info.chooseIdentity(),
weAreBaseCurrencySeller = false)) weAreBaseCurrencySeller = false))
// wait for the flow to finish and the vault updates to be done // wait for the flow to finish and the vault updates to be done
doIt.resultFuture.getOrThrow() doIt.getOrThrow()
// Get the balances when the vault updates // Get the balances when the vault updates
nodeAVaultUpdate.get() nodeAVaultUpdate.get()
val balancesA = nodeA.database.transaction { val balancesA = nodeA.database.transaction {

View File

@ -56,7 +56,7 @@ class WorkflowTransactionBuildTutorialTest {
// Kick of the proposal flow // Kick of the proposal flow
val flow1 = aliceServices.startFlow(SubmitTradeApprovalFlow("1234", bob)) val flow1 = aliceServices.startFlow(SubmitTradeApprovalFlow("1234", bob))
// Wait for the flow to finish // Wait for the flow to finish
val proposalRef = flow1.resultFuture.getOrThrow() val proposalRef = flow1.getOrThrow()
val proposalLinearId = proposalRef.state.data.linearId val proposalLinearId = proposalRef.state.data.linearId
// Wait for NodeB to include it's copy in the vault // Wait for NodeB to include it's copy in the vault
nodeBVaultUpdate.get() nodeBVaultUpdate.get()
@ -80,7 +80,7 @@ class WorkflowTransactionBuildTutorialTest {
// Run the manual completion flow from NodeB // Run the manual completion flow from NodeB
val flow2 = bobServices.startFlow(SubmitCompletionFlow(latestFromB.ref, WorkflowState.APPROVED)) val flow2 = bobServices.startFlow(SubmitCompletionFlow(latestFromB.ref, WorkflowState.APPROVED))
// wait for the flow to end // wait for the flow to end
val completedRef = flow2.resultFuture.getOrThrow() val completedRef = flow2.getOrThrow()
// wait for the vault updates to stabilise // wait for the vault updates to stabilise
nodeAVaultUpdate.get() nodeAVaultUpdate.get()
secondNodeBVaultUpdate.get() secondNodeBVaultUpdate.get()

View File

@ -31,10 +31,10 @@ class CashSelectionH2ImplTest {
// spend operation below. // spend operation below.
// Issuing Integer.MAX_VALUE will not cause an exception since PersistentCashState.pennies is a long // Issuing Integer.MAX_VALUE will not cause an exception since PersistentCashState.pennies is a long
nCopies(2, Integer.MAX_VALUE).map { issueAmount -> nCopies(2, Integer.MAX_VALUE).map { issueAmount ->
node.services.startFlow(CashIssueFlow(issueAmount.POUNDS, OpaqueBytes.of(1), mockNet.defaultNotaryIdentity)).resultFuture node.services.startFlow(CashIssueFlow(issueAmount.POUNDS, OpaqueBytes.of(1), mockNet.defaultNotaryIdentity))
}.transpose().getOrThrow() }.transpose().getOrThrow()
// The spend must be more than the size of a single cash state to force the accumulator onto the second state. // The spend must be more than the size of a single cash state to force the accumulator onto the second state.
node.services.startFlow(CashPaymentFlow((Integer.MAX_VALUE + 1L).POUNDS, node.info.legalIdentities[0])).resultFuture.getOrThrow() node.services.startFlow(CashPaymentFlow((Integer.MAX_VALUE + 1L).POUNDS, node.info.legalIdentities[0])).getOrThrow()
} }
@Test @Test
@ -50,8 +50,8 @@ class CashSelectionH2ImplTest {
val flow2 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notary)) val flow2 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notary))
val flow3 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notary)) val flow3 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notary))
assertThatThrownBy { flow1.resultFuture.getOrThrow() }.isInstanceOf(CashException::class.java) assertThatThrownBy { flow1.getOrThrow() }.isInstanceOf(CashException::class.java)
assertThatThrownBy { flow2.resultFuture.getOrThrow() }.isInstanceOf(CashException::class.java) assertThatThrownBy { flow2.getOrThrow() }.isInstanceOf(CashException::class.java)
assertThatThrownBy { flow3.resultFuture.getOrThrow() }.isInstanceOf(CashException::class.java) assertThatThrownBy { flow3.getOrThrow() }.isInstanceOf(CashException::class.java)
} }
} }

View File

@ -33,7 +33,7 @@ class CashExitFlowTests {
bankOfCordaNode = mockNet.createPartyNode(BOC_NAME) bankOfCordaNode = mockNet.createPartyNode(BOC_NAME)
bankOfCorda = bankOfCordaNode.info.identityFromX500Name(BOC_NAME) bankOfCorda = bankOfCordaNode.info.identityFromX500Name(BOC_NAME)
notary = mockNet.defaultNotaryIdentity notary = mockNet.defaultNotaryIdentity
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary))
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() future.getOrThrow()
} }
@ -46,7 +46,7 @@ class CashExitFlowTests {
@Test @Test
fun `exit some cash`() { fun `exit some cash`() {
val exitAmount = 500.DOLLARS val exitAmount = 500.DOLLARS
val future = bankOfCordaNode.services.startFlow(CashExitFlow(exitAmount, ref)).resultFuture val future = bankOfCordaNode.services.startFlow(CashExitFlow(exitAmount, ref))
mockNet.runNetwork() mockNet.runNetwork()
val exitTx = future.getOrThrow().stx.tx val exitTx = future.getOrThrow().stx.tx
val expected = (initialBalance - exitAmount).`issued by`(bankOfCorda.ref(ref)) val expected = (initialBalance - exitAmount).`issued by`(bankOfCorda.ref(ref))
@ -59,7 +59,7 @@ class CashExitFlowTests {
@Test @Test
fun `exit zero cash`() { fun `exit zero cash`() {
val expected = 0.DOLLARS val expected = 0.DOLLARS
val future = bankOfCordaNode.services.startFlow(CashExitFlow(expected, ref)).resultFuture val future = bankOfCordaNode.services.startFlow(CashExitFlow(expected, ref))
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith<CashException> { assertFailsWith<CashException> {
future.getOrThrow() future.getOrThrow()

View File

@ -41,7 +41,7 @@ class CashIssueFlowTests {
fun `issue some cash`() { fun `issue some cash`() {
val expected = 500.DOLLARS val expected = 500.DOLLARS
val ref = OpaqueBytes.of(0x01) val ref = OpaqueBytes.of(0x01)
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(expected, ref, notary)).resultFuture val future = bankOfCordaNode.services.startFlow(CashIssueFlow(expected, ref, notary))
mockNet.runNetwork() mockNet.runNetwork()
val issueTx = future.getOrThrow().stx val issueTx = future.getOrThrow().stx
val output = issueTx.tx.outputsOfType<Cash.State>().single() val output = issueTx.tx.outputsOfType<Cash.State>().single()
@ -52,7 +52,7 @@ class CashIssueFlowTests {
fun `issue zero cash`() { fun `issue zero cash`() {
val expected = 0.DOLLARS val expected = 0.DOLLARS
val ref = OpaqueBytes.of(0x01) val ref = OpaqueBytes.of(0x01)
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(expected, ref, notary)).resultFuture val future = bankOfCordaNode.services.startFlow(CashIssueFlow(expected, ref, notary))
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith<IllegalArgumentException> { assertFailsWith<IllegalArgumentException> {
future.getOrThrow() future.getOrThrow()

View File

@ -35,7 +35,7 @@ class CashPaymentFlowTests {
bankOfCordaNode = mockNet.createPartyNode(BOC_NAME) bankOfCordaNode = mockNet.createPartyNode(BOC_NAME)
bankOfCorda = bankOfCordaNode.info.identityFromX500Name(BOC_NAME) bankOfCorda = bankOfCordaNode.info.identityFromX500Name(BOC_NAME)
aliceNode = mockNet.createPartyNode(ALICE_NAME) aliceNode = mockNet.createPartyNode(ALICE_NAME)
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, mockNet.defaultNotaryIdentity)).resultFuture val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, mockNet.defaultNotaryIdentity))
future.getOrThrow() future.getOrThrow()
} }
@ -56,8 +56,7 @@ class CashPaymentFlowTests {
val (_, vaultUpdatesBoc) = bankOfCordaNode.services.vaultService.trackBy<Cash.State>(criteria) val (_, vaultUpdatesBoc) = bankOfCordaNode.services.vaultService.trackBy<Cash.State>(criteria)
val (_, vaultUpdatesBankClient) = aliceNode.services.vaultService.trackBy<Cash.State>(criteria) val (_, vaultUpdatesBankClient) = aliceNode.services.vaultService.trackBy<Cash.State>(criteria)
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expectedPayment, val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expectedPayment, payTo))
payTo)).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() future.getOrThrow()
@ -89,7 +88,7 @@ class CashPaymentFlowTests {
val payTo = aliceNode.info.chooseIdentity() val payTo = aliceNode.info.chooseIdentity()
val expected = 4000.DOLLARS val expected = 4000.DOLLARS
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected, val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected,
payTo)).resultFuture payTo))
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith<CashException> { assertFailsWith<CashException> {
future.getOrThrow() future.getOrThrow()
@ -101,7 +100,7 @@ class CashPaymentFlowTests {
val payTo = aliceNode.info.chooseIdentity() val payTo = aliceNode.info.chooseIdentity()
val expected = 0.DOLLARS val expected = 0.DOLLARS
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected, val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected,
payTo)).resultFuture payTo))
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith<IllegalArgumentException> { assertFailsWith<IllegalArgumentException> {
future.getOrThrow() future.getOrThrow()

View File

@ -92,7 +92,7 @@ class BFTNotaryServiceTests {
addOutputState(DummyContract.SingleOwnerState(owner = info.chooseIdentity()), DummyContract.PROGRAM_ID, AlwaysAcceptAttachmentConstraint) addOutputState(DummyContract.SingleOwnerState(owner = info.chooseIdentity()), DummyContract.PROGRAM_ID, AlwaysAcceptAttachmentConstraint)
} }
// Create a new consensus while the redundant replica is sleeping: // Create a new consensus while the redundant replica is sleeping:
services.startFlow(NotaryFlow.Client(trivialTx)).resultFuture services.startFlow(NotaryFlow.Client(trivialTx))
} }
mockNet.runNetwork() mockNet.runNetwork()
f.getOrThrow() f.getOrThrow()
@ -127,7 +127,7 @@ class BFTNotaryServiceTests {
val flows = spendTxs.map { NotaryFlow.Client(it) } val flows = spendTxs.map { NotaryFlow.Client(it) }
val stateMachines = flows.map { services.startFlow(it) } val stateMachines = flows.map { services.startFlow(it) }
mockNet.runNetwork() mockNet.runNetwork()
val results = stateMachines.map { Try.on { it.resultFuture.getOrThrow() } } val results = stateMachines.map { Try.on { it.getOrThrow() } }
val successfulIndex = results.mapIndexedNotNull { index, result -> val successfulIndex = results.mapIndexedNotNull { index, result ->
if (result is Try.Success) { if (result is Try.Success) {
val signers = result.value.map { it.by } val signers = result.value.map { it.by }

View File

@ -44,7 +44,7 @@ class RaftNotaryServiceTests {
val firstSpendTx = bankA.services.signInitialTransaction(firstTxBuilder) val firstSpendTx = bankA.services.signInitialTransaction(firstTxBuilder)
val firstSpend = bankA.services.startFlow(NotaryFlow.Client(firstSpendTx)) val firstSpend = bankA.services.startFlow(NotaryFlow.Client(firstSpendTx))
firstSpend.resultFuture.getOrThrow() firstSpend.getOrThrow()
val secondSpendBuilder = TransactionBuilder(defaultNotaryIdentity).withItems(inputState).run { val secondSpendBuilder = TransactionBuilder(defaultNotaryIdentity).withItems(inputState).run {
val dummyState = DummyContract.SingleOwnerState(0, bankA.info.chooseIdentity()) val dummyState = DummyContract.SingleOwnerState(0, bankA.info.chooseIdentity())
@ -55,7 +55,7 @@ class RaftNotaryServiceTests {
val secondSpendTx = bankA.services.signInitialTransaction(secondSpendBuilder) val secondSpendTx = bankA.services.signInitialTransaction(secondSpendBuilder)
val secondSpend = bankA.services.startFlow(NotaryFlow.Client(secondSpendTx)) val secondSpend = bankA.services.startFlow(NotaryFlow.Client(secondSpendTx))
val ex = assertFailsWith(NotaryException::class) { secondSpend.resultFuture.getOrThrow() } val ex = assertFailsWith(NotaryException::class) { secondSpend.getOrThrow() }
val error = ex.error as NotaryError.Conflict val error = ex.error as NotaryError.Conflict
assertEquals(error.txId, secondSpendTx.id) assertEquals(error.txId, secondSpendTx.id)
} }

View File

@ -22,7 +22,7 @@ class FlowVersioningTest : NodeBasedTest() {
val bob = startNode(BOB_NAME, platformVersion = 3) val bob = startNode(BOB_NAME, platformVersion = 3)
bob.internals.installCoreFlow(PretendInitiatingCoreFlow::class, ::PretendInitiatedCoreFlow) bob.internals.installCoreFlow(PretendInitiatingCoreFlow::class, ::PretendInitiatedCoreFlow)
val (alicePlatformVersionAccordingToBob, bobPlatformVersionAccordingToAlice) = alice.services.startFlow( val (alicePlatformVersionAccordingToBob, bobPlatformVersionAccordingToAlice) = alice.services.startFlow(
PretendInitiatingCoreFlow(bob.info.chooseIdentity())).resultFuture.getOrThrow() PretendInitiatingCoreFlow(bob.info.chooseIdentity())).getOrThrow()
assertThat(alicePlatformVersionAccordingToBob).isEqualTo(2) assertThat(alicePlatformVersionAccordingToBob).isEqualTo(2)
assertThat(bobPlatformVersionAccordingToAlice).isEqualTo(3) assertThat(bobPlatformVersionAccordingToAlice).isEqualTo(3)
} }

View File

@ -3,9 +3,7 @@ package net.corda.services.messaging
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import net.corda.client.rpc.CordaRPCClient import net.corda.client.rpc.CordaRPCClient
import net.corda.client.rpc.CordaRPCConnection import net.corda.client.rpc.CordaRPCConnection
import net.corda.core.crypto.generateKeyPair
import net.corda.core.crypto.random63BitValue import net.corda.core.crypto.random63BitValue
import net.corda.core.crypto.toStringShort
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowSession import net.corda.core.flows.FlowSession
import net.corda.core.flows.InitiatedBy import net.corda.core.flows.InitiatedBy
@ -193,7 +191,7 @@ abstract class MQSecurityTest : NodeBasedTest() {
bob.registerInitiatedFlow(ReceiveFlow::class.java) bob.registerInitiatedFlow(ReceiveFlow::class.java)
val bobParty = bob.info.chooseIdentity() val bobParty = bob.info.chooseIdentity()
// Perform a protocol exchange to force the peer queue to be created // Perform a protocol exchange to force the peer queue to be created
alice.services.startFlow(SendFlow(bobParty, 0)).resultFuture.getOrThrow() alice.services.startFlow(SendFlow(bobParty, 0)).getOrThrow()
return bobParty return bobParty
} }

View File

@ -67,7 +67,7 @@ class NetworkParametersTest {
val alice = mockNet.createPartyNode(ALICE_NAME) val alice = mockNet.createPartyNode(ALICE_NAME)
assertThat(alice.services.networkMapCache.notaryIdentities).doesNotContain(fakeNotaryId) assertThat(alice.services.networkMapCache.notaryIdentities).doesNotContain(fakeNotaryId)
assertFails { assertFails {
alice.services.startFlow(CashIssueFlow(500.DOLLARS, OpaqueBytes.of(0x01), fakeNotaryId)).resultFuture.getOrThrow() alice.services.startFlow(CashIssueFlow(500.DOLLARS, OpaqueBytes.of(0x01), fakeNotaryId)).getOrThrow()
} }
} }

View File

@ -536,7 +536,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
val buyerFlows: Observable<out FlowLogic<*>> = buyerNode.registerInitiatedFlow(BuyerAcceptor::class.java) val buyerFlows: Observable<out FlowLogic<*>> = buyerNode.registerInitiatedFlow(BuyerAcceptor::class.java)
val firstBuyerFiber = buyerFlows.toFuture().map { it.stateMachine } val firstBuyerFiber = buyerFlows.toFuture().map { it.stateMachine }
val seller = SellerInitiator(buyer, notary, assetToSell, 1000.DOLLARS, anonymous) val seller = SellerInitiator(buyer, notary, assetToSell, 1000.DOLLARS, anonymous)
val sellerResult = sellerNode.services.startFlow(seller).resultFuture val sellerResult = sellerNode.services.startFlow(seller)
return RunResult(firstBuyerFiber, sellerResult, seller.stateMachine.id) return RunResult(firstBuyerFiber, sellerResult, seller.stateMachine.id)
} }

View File

@ -74,7 +74,7 @@ class NotaryChangeTests {
mockNet.runNetwork() mockNet.runNetwork()
val newState = future.resultFuture.getOrThrow() val newState = future.getOrThrow()
assertEquals(newState.state.notary, newNotary) assertEquals(newState.state.notary, newNotary)
val loadedStateA = clientNodeA.services.loadState(newState.ref) val loadedStateA = clientNodeA.services.loadState(newState.ref)
val loadedStateB = clientNodeB.services.loadState(newState.ref) val loadedStateB = clientNodeB.services.loadState(newState.ref)
@ -91,7 +91,7 @@ class NotaryChangeTests {
mockNet.runNetwork() mockNet.runNetwork()
assertThatExceptionOfType(StateReplacementException::class.java).isThrownBy { assertThatExceptionOfType(StateReplacementException::class.java).isThrownBy {
future.resultFuture.getOrThrow() future.getOrThrow()
} }
} }
@ -104,7 +104,7 @@ class NotaryChangeTests {
val flow = NotaryChangeFlow(state, newNotary) val flow = NotaryChangeFlow(state, newNotary)
val future = clientNodeA.services.startFlow(flow) val future = clientNodeA.services.startFlow(flow)
mockNet.runNetwork() mockNet.runNetwork()
val newState = future.resultFuture.getOrThrow() val newState = future.getOrThrow()
assertEquals(newState.state.notary, newNotary) assertEquals(newState.state.notary, newNotary)
val recordedTx = clientNodeA.services.validatedTransactions.getTransaction(newState.ref.txhash)!! val recordedTx = clientNodeA.services.validatedTransactions.getTransaction(newState.ref.txhash)!!
@ -150,7 +150,7 @@ class NotaryChangeTests {
val future = node.services.startFlow(flow) val future = node.services.startFlow(flow)
mockNet.runNetwork() mockNet.runNetwork()
return future.resultFuture.getOrThrow() return future.getOrThrow()
} }
private fun moveState(state: StateAndRef<DummyContract.SingleOwnerState>, fromNode: StartedNode<*>, toNode: StartedNode<*>): StateAndRef<DummyContract.SingleOwnerState> { private fun moveState(state: StateAndRef<DummyContract.SingleOwnerState>, fromNode: StartedNode<*>, toNode: StartedNode<*>): StateAndRef<DummyContract.SingleOwnerState> {
@ -161,7 +161,7 @@ class NotaryChangeTests {
val future = fromNode.services.startFlow(notaryFlow) val future = fromNode.services.startFlow(notaryFlow)
mockNet.runNetwork() mockNet.runNetwork()
val notarySignature = future.resultFuture.getOrThrow() val notarySignature = future.getOrThrow()
val finalTransaction = stx + notarySignature val finalTransaction = stx + notarySignature
fromNode.services.recordTransactions(finalTransaction) fromNode.services.recordTransactions(finalTransaction)

View File

@ -143,8 +143,8 @@ class ScheduledFlowTests {
val N = 100 val N = 100
val futures = mutableListOf<CordaFuture<*>>() val futures = mutableListOf<CordaFuture<*>>()
for (i in 0 until N) { for (i in 0 until N) {
futures.add(aliceNode.services.startFlow(InsertInitialStateFlow(bob, notary)).resultFuture) futures.add(aliceNode.services.startFlow(InsertInitialStateFlow(bob, notary)))
futures.add(bobNode.services.startFlow(InsertInitialStateFlow(alice, notary)).resultFuture) futures.add(bobNode.services.startFlow(InsertInitialStateFlow(alice, notary)))
} }
mockNet.waitQuiescent() mockNet.waitQuiescent()

View File

@ -38,7 +38,7 @@ import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetwork.MockNode import net.corda.testing.node.MockNetwork.MockNode
import net.corda.testing.node.MockNodeParameters import net.corda.testing.node.MockNodeParameters
import net.corda.testing.node.pumpReceive import net.corda.testing.node.pumpReceive
import net.corda.testing.node.startFlow import net.corda.testing.node.internal.startFlow
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy import org.assertj.core.api.Assertions.assertThatThrownBy
import org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType import org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType

View File

@ -19,8 +19,8 @@ import net.corda.testing.contracts.DummyContract
import net.corda.testing.core.dummyCommand import net.corda.testing.core.dummyCommand
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNodeParameters import net.corda.testing.node.MockNodeParameters
import net.corda.testing.node.startFlow
import net.corda.testing.core.singleIdentity import net.corda.testing.core.singleIdentity
import net.corda.testing.node.startFlow
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@ -120,11 +120,11 @@ class NotaryServiceTests {
// Note that the notary will only return identical signatures when using deterministic signature // Note that the notary will only return identical signatures when using deterministic signature
// schemes (e.g. EdDSA) and when deterministic metadata is attached (no timestamps or nonces). // schemes (e.g. EdDSA) and when deterministic metadata is attached (no timestamps or nonces).
// We only really care that both signatures are over the same transaction and by the same notary. // We only really care that both signatures are over the same transaction and by the same notary.
val sig1 = f1.resultFuture.getOrThrow().single() val sig1 = f1.getOrThrow().single()
assertEquals(sig1.by, notary.owningKey) assertEquals(sig1.by, notary.owningKey)
assertTrue(sig1.isValid(stx.id)) assertTrue(sig1.isValid(stx.id))
val sig2 = f2.resultFuture.getOrThrow().single() val sig2 = f2.getOrThrow().single()
assertEquals(sig2.by, notary.owningKey) assertEquals(sig2.by, notary.owningKey)
assertTrue(sig2.isValid(stx.id)) assertTrue(sig2.isValid(stx.id))
} }
@ -153,7 +153,7 @@ class NotaryServiceTests {
mockNet.runNetwork() mockNet.runNetwork()
val ex = assertFailsWith(NotaryException::class) { future.resultFuture.getOrThrow() } val ex = assertFailsWith(NotaryException::class) { future.getOrThrow() }
val notaryError = ex.error as NotaryError.Conflict val notaryError = ex.error as NotaryError.Conflict
assertEquals(notaryError.txId, stx2.id) assertEquals(notaryError.txId, stx2.id)
notaryError.conflict.verified() notaryError.conflict.verified()
@ -161,7 +161,7 @@ class NotaryServiceTests {
private fun runNotaryClient(stx: SignedTransaction): CordaFuture<List<TransactionSignature>> { private fun runNotaryClient(stx: SignedTransaction): CordaFuture<List<TransactionSignature>> {
val flow = NotaryFlow.Client(stx) val flow = NotaryFlow.Client(stx)
val future = aliceServices.startFlow(flow).resultFuture val future = aliceServices.startFlow(flow)
mockNet.runNetwork() mockNet.runNetwork()
return future return future
} }

View File

@ -94,7 +94,7 @@ class ValidatingNotaryServiceTests {
private fun runClient(stx: SignedTransaction): CordaFuture<List<TransactionSignature>> { private fun runClient(stx: SignedTransaction): CordaFuture<List<TransactionSignature>> {
val flow = NotaryFlow.Client(stx) val flow = NotaryFlow.Client(stx)
val future = aliceServices.startFlow(flow).resultFuture val future = aliceServices.startFlow(flow)
mockNet.runNetwork() mockNet.runNetwork()
return future return future
} }

View File

@ -227,7 +227,7 @@ class NodeInterestRatesTest {
val flow = FilteredRatesFlow(tx, oracle, fixOf, BigDecimal("0.675"), BigDecimal("0.1")) val flow = FilteredRatesFlow(tx, oracle, fixOf, BigDecimal("0.675"), BigDecimal("0.1"))
LogHelper.setLevel("rates") LogHelper.setLevel("rates")
mockNet.runNetwork() mockNet.runNetwork()
val future = aliceNode.services.startFlow(flow).resultFuture val future = aliceNode.services.startFlow(flow)
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() future.getOrThrow()
// We should now have a valid fix of our tx from the oracle. // We should now have a valid fix of our tx from the oracle.

View File

@ -160,7 +160,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
val instigator = StartDealFlow( val instigator = StartDealFlow(
node2.info.chooseIdentity(), node2.info.chooseIdentity(),
AutoOffer(mockNet.defaultNotaryIdentity, irs)) // TODO Pass notary as parameter to Simulation. AutoOffer(mockNet.defaultNotaryIdentity, irs)) // TODO Pass notary as parameter to Simulation.
val instigatorTxFuture = node1.services.startFlow(instigator).resultFuture val instigatorTxFuture = node1.services.startFlow(instigator)
return allOf(instigatorTxFuture.toCompletableFuture(), acceptorTxFuture).thenCompose { instigatorTxFuture.toCompletableFuture() } return allOf(instigatorTxFuture.toCompletableFuture(), acceptorTxFuture).thenCompose { instigatorTxFuture.toCompletableFuture() }
} }

View File

@ -290,7 +290,7 @@ class FlowStackSnapshotTest {
val mockNet = MockNetwork(emptyList(), threadPerNode = true) val mockNet = MockNetwork(emptyList(), threadPerNode = true)
val node = mockNet.createPartyNode() val node = mockNet.createPartyNode()
node.registerInitiatedFlow(DummyFlow::class.java) node.registerInitiatedFlow(DummyFlow::class.java)
node.services.startFlow(FlowStackSnapshotSerializationTestingFlow()).resultFuture.get() node.services.startFlow(FlowStackSnapshotSerializationTestingFlow()).get()
val thrown = try { val thrown = try {
// Due to the [MockNetwork] implementation, the easiest way to trigger object serialization process is at // Due to the [MockNetwork] implementation, the easiest way to trigger object serialization process is at
// the network stopping stage. // the network stopping stage.

View File

@ -263,4 +263,4 @@ data class DriverParameters(
fun setNotarySpecs(notarySpecs: List<NotarySpec>) = copy(notarySpecs = notarySpecs) fun setNotarySpecs(notarySpecs: List<NotarySpec>) = copy(notarySpecs = notarySpecs)
fun setExtraCordappPackagesToScan(extraCordappPackagesToScan: List<String>) = copy(extraCordappPackagesToScan = extraCordappPackagesToScan) fun setExtraCordappPackagesToScan(extraCordappPackagesToScan: List<String>) = copy(extraCordappPackagesToScan = extraCordappPackagesToScan)
fun setJmxPolicy(jmxPolicy: JmxPolicy) = copy(jmxPolicy = jmxPolicy) fun setJmxPolicy(jmxPolicy: JmxPolicy) = copy(jmxPolicy = jmxPolicy)
} }

View File

@ -2,6 +2,7 @@
package net.corda.testing.node package net.corda.testing.node
import net.corda.core.concurrent.CordaFuture
import net.corda.core.context.Actor import net.corda.core.context.Actor
import net.corda.core.context.AuthServiceId import net.corda.core.context.AuthServiceId
import net.corda.core.context.InvocationContext import net.corda.core.context.InvocationContext
@ -60,13 +61,13 @@ fun testActor(owningLegalIdentity: CordaX500Name = CordaX500Name("Test Company I
fun testContext(owningLegalIdentity: CordaX500Name = CordaX500Name("Test Company Inc.", "London", "GB")) = InvocationContext.rpc(testActor(owningLegalIdentity)) fun testContext(owningLegalIdentity: CordaX500Name = CordaX500Name("Test Company Inc.", "London", "GB")) = InvocationContext.rpc(testActor(owningLegalIdentity))
/**
* Starts an already constructed flow. Note that you must be on the server thread to call this method. [InvocationContext]
* has origin [Origin.RPC] and actor with id "Only For Testing".
*/
fun <T> StartedNodeServices.startFlow(logic: FlowLogic<T>): FlowStateMachine<T> = startFlow(logic, newContext()).getOrThrow()
/** /**
* Creates a new [InvocationContext] for testing purposes. * Creates a new [InvocationContext] for testing purposes.
*/ */
fun StartedNodeServices.newContext() = testContext(myInfo.chooseIdentity().name) fun StartedNodeServices.newContext() = testContext(myInfo.chooseIdentity().name)
/**
* Starts an already constructed flow. Note that you must be on the server thread to call this method. [InvocationContext]
* has origin [Origin.RPC] and actor with id "Only For Testing".
*/
fun <T> StartedNodeServices.startFlow(logic: FlowLogic<T>): CordaFuture<T> = startFlow(logic, newContext()).getOrThrow().resultFuture

View File

@ -2,12 +2,16 @@ package net.corda.testing.node.internal
import net.corda.core.CordaException import net.corda.core.CordaException
import net.corda.core.concurrent.CordaFuture import net.corda.core.concurrent.CordaFuture
import net.corda.core.flows.FlowLogic
import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.concurrent.openFuture import net.corda.core.internal.concurrent.openFuture
import net.corda.core.internal.times import net.corda.core.internal.times
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.millis import net.corda.core.utilities.millis
import net.corda.core.utilities.seconds import net.corda.core.utilities.seconds
import net.corda.node.services.api.StartedNodeServices
import net.corda.testing.node.newContext
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.net.Socket import java.net.Socket
import java.net.SocketException import java.net.SocketException
@ -91,3 +95,5 @@ fun <A> poll(
class ListenProcessDeathException(hostAndPort: NetworkHostAndPort, listenProcess: Process) : class ListenProcessDeathException(hostAndPort: NetworkHostAndPort, listenProcess: Process) :
CordaException("The process that was expected to listen on $hostAndPort has died with status: ${listenProcess.exitValue()}") CordaException("The process that was expected to listen on $hostAndPort has died with status: ${listenProcess.exitValue()}")
fun <T> StartedNodeServices.startFlow(logic: FlowLogic<T>): FlowStateMachine<T> = startFlow(logic, newContext()).getOrThrow()