CORDA-652: Remove uses of createSomeNodes for consistency (#1492)

Replace use of `createSomeNodes()` with creating notary and party nodes individually. This typically results in less code as the basket of nodes isn't built first then the nodes, but instead the nodes generated directly. Notably this identified issues in notary change and contract upgrade tests, which were not actually using a validating notary and therefore it had been missed that the transactions were failing validation.

Renamed nodes in tests for consistency as well, so nodes are now `aliceNode`, `bobNode`, etc. instead of `a`, `b`, or `n0`, `n1`, or other variants of those.
This commit is contained in:
Ross Nicoll
2017-09-28 17:12:21 +01:00
committed by GitHub
parent 5e5f9d7790
commit 2aaeb4c0b5
14 changed files with 238 additions and 268 deletions

View File

@ -40,7 +40,7 @@ class IdentitySyncFlowTests {
@Test @Test
fun `sync confidential identities`() { fun `sync confidential identities`() {
// Set up values we'll need // Set up values we'll need
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name) val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val alice: Party = aliceNode.services.myInfo.chooseIdentity() val alice: Party = aliceNode.services.myInfo.chooseIdentity()

View File

@ -22,7 +22,7 @@ class SwapIdentitiesFlowTests {
val mockNet = MockNetwork(false, true) val mockNet = MockNetwork(false, true)
// Set up values we'll need // Set up values we'll need
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name) val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val alice: Party = aliceNode.services.myInfo.chooseIdentity() val alice: Party = aliceNode.services.myInfo.chooseIdentity()

View File

@ -5,6 +5,7 @@ import com.google.common.primitives.Primitives;
import net.corda.core.identity.Party; import net.corda.core.identity.Party;
import net.corda.node.internal.StartedNode; import net.corda.node.internal.StartedNode;
import net.corda.testing.node.MockNetwork; import net.corda.testing.node.MockNetwork;
import net.corda.testing.TestConstants;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -19,17 +20,18 @@ import static org.junit.Assert.fail;
public class FlowsInJavaTest { public class FlowsInJavaTest {
private final MockNetwork mockNet = new MockNetwork(); private final MockNetwork mockNet = new MockNetwork();
private StartedNode<MockNetwork.MockNode> node1; private StartedNode<MockNetwork.MockNode> notaryNode;
private StartedNode<MockNetwork.MockNode> node2; private StartedNode<MockNetwork.MockNode> aliceNode;
private StartedNode<MockNetwork.MockNode> bobNode;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
MockNetwork.BasketOfNodes someNodes = mockNet.createSomeNodes(2); notaryNode = mockNet.createNotaryNode();
node1 = someNodes.getPartyNodes().get(0); aliceNode = mockNet.createPartyNode(notaryNode.getNetwork().getMyAddress(), TestConstants.getALICE().getName());
node2 = someNodes.getPartyNodes().get(1); bobNode = mockNet.createPartyNode(notaryNode.getNetwork().getMyAddress(), TestConstants.getBOB().getName());
mockNet.runNetwork(); mockNet.runNetwork();
// Ensure registration was successful // Ensure registration was successful
node1.getInternals().getNodeReadyFuture().get(); aliceNode.getInternals().getNodeReadyFuture().get();
} }
@After @After
@ -39,8 +41,8 @@ public class FlowsInJavaTest {
@Test @Test
public void suspendableActionInsideUnwrap() throws Exception { public void suspendableActionInsideUnwrap() throws Exception {
node2.getInternals().registerInitiatedFlow(SendHelloAndThenReceive.class); bobNode.getInternals().registerInitiatedFlow(SendHelloAndThenReceive.class);
Future<String> result = node1.getServices().startFlow(new SendInUnwrapFlow(chooseIdentity(node2.getInfo()))).getResultFuture(); Future<String> result = aliceNode.getServices().startFlow(new SendInUnwrapFlow(chooseIdentity(bobNode.getInfo()))).getResultFuture();
mockNet.runNetwork(); mockNet.runNetwork();
assertThat(result.get()).isEqualTo("Hello"); assertThat(result.get()).isEqualTo("Hello");
} }
@ -55,8 +57,8 @@ public class FlowsInJavaTest {
} }
private void primitiveReceiveTypeTest(Class<?> receiveType) throws InterruptedException { private void primitiveReceiveTypeTest(Class<?> receiveType) throws InterruptedException {
PrimitiveReceiveFlow flow = new PrimitiveReceiveFlow(chooseIdentity(node2.getInfo()), receiveType); PrimitiveReceiveFlow flow = new PrimitiveReceiveFlow(chooseIdentity(bobNode.getInfo()), receiveType);
Future<?> result = node1.getServices().startFlow(flow).getResultFuture(); Future<?> result = aliceNode.getServices().startFlow(flow).getResultFuture();
mockNet.runNetwork(); mockNet.runNetwork();
try { try {
result.get(); result.get();

View File

@ -10,12 +10,14 @@ import net.corda.core.internal.FetchDataFlow
import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.node.internal.StartedNode import net.corda.node.internal.StartedNode
import net.corda.nodeapi.internal.ServiceInfo
import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.network.NetworkMapService import net.corda.node.services.network.NetworkMapService
import net.corda.node.services.persistence.NodeAttachmentService import net.corda.node.services.persistence.NodeAttachmentService
import net.corda.node.services.transactions.SimpleNotaryService import net.corda.node.services.transactions.SimpleNotaryService
import net.corda.node.utilities.DatabaseTransactionManager import net.corda.node.utilities.DatabaseTransactionManager
import net.corda.nodeapi.internal.ServiceInfo
import net.corda.testing.ALICE
import net.corda.testing.BOB
import net.corda.testing.chooseIdentity import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.After import org.junit.After
@ -55,68 +57,68 @@ class AttachmentTests {
@Test @Test
fun `download and store`() { fun `download and store`() {
val nodes = mockNet.createSomeNodes(2) val notaryNode = mockNet.createNotaryNode()
val n0 = nodes.partyNodes[0] val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val n1 = nodes.partyNodes[1] val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
// Ensure that registration was successful before progressing any further // Ensure that registration was successful before progressing any further
mockNet.runNetwork() mockNet.runNetwork()
n0.internals.ensureRegistered() aliceNode.internals.ensureRegistered()
n0.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java) aliceNode.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
n1.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java) bobNode.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
// Insert an attachment into node zero's store directly. // Insert an attachment into node zero's store directly.
val id = n0.database.transaction { val id = aliceNode.database.transaction {
n0.attachments.importAttachment(ByteArrayInputStream(fakeAttachment())) aliceNode.attachments.importAttachment(ByteArrayInputStream(fakeAttachment()))
} }
// Get node one to run a flow to fetch it and insert it. // Get node one to run a flow to fetch it and insert it.
mockNet.runNetwork() mockNet.runNetwork()
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.chooseIdentity()) val bobFlow = bobNode.startAttachmentFlow(setOf(id), aliceNode.info.chooseIdentity())
mockNet.runNetwork() mockNet.runNetwork()
assertEquals(0, f1.resultFuture.getOrThrow().fromDisk.size) assertEquals(0, bobFlow.resultFuture.getOrThrow().fromDisk.size)
// Verify it was inserted into node one's store. // Verify it was inserted into node one's store.
val attachment = n1.database.transaction { val attachment = bobNode.database.transaction {
n1.attachments.openAttachment(id)!! bobNode.attachments.openAttachment(id)!!
} }
assertEquals(id, attachment.open().readBytes().sha256()) assertEquals(id, attachment.open().readBytes().sha256())
// 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.
n0.dispose() aliceNode.dispose()
val response: FetchDataFlow.Result<Attachment> = n1.startAttachmentFlow(setOf(id), n0.info.chooseIdentity()).resultFuture.getOrThrow() val response: FetchDataFlow.Result<Attachment> = bobNode.startAttachmentFlow(setOf(id), aliceNode.info.chooseIdentity()).resultFuture.getOrThrow()
assertEquals(attachment, response.fromDisk[0]) assertEquals(attachment, response.fromDisk[0])
} }
@Test @Test
fun `missing`() { fun `missing`() {
val nodes = mockNet.createSomeNodes(2) val notaryNode = mockNet.createNotaryNode()
val n0 = nodes.partyNodes[0] val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val n1 = nodes.partyNodes[1] val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
// Ensure that registration was successful before progressing any further // Ensure that registration was successful before progressing any further
mockNet.runNetwork() mockNet.runNetwork()
n0.internals.ensureRegistered() aliceNode.internals.ensureRegistered()
n0.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java) aliceNode.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
n1.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java) bobNode.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
// Get node one to fetch a non-existent attachment. // Get node one to fetch a non-existent attachment.
val hash = SecureHash.randomSHA256() val hash = SecureHash.randomSHA256()
mockNet.runNetwork() mockNet.runNetwork()
val f1 = n1.startAttachmentFlow(setOf(hash), n0.info.chooseIdentity()) val bobFlow = bobNode.startAttachmentFlow(setOf(hash), aliceNode.info.chooseIdentity())
mockNet.runNetwork() mockNet.runNetwork()
val e = assertFailsWith<FetchDataFlow.HashNotFound> { f1.resultFuture.getOrThrow() } val e = assertFailsWith<FetchDataFlow.HashNotFound> { bobFlow.resultFuture.getOrThrow() }
assertEquals(hash, e.requested) assertEquals(hash, e.requested)
} }
@Test @Test
fun `malicious response`() { fun `malicious response`() {
// Make a node that doesn't do sanity checking at load time. // Make a node that doesn't do sanity checking at load time.
val n0 = mockNet.createNode(nodeFactory = object : MockNetwork.Factory<MockNetwork.MockNode> { val aliceNode = mockNet.createNode(legalName = ALICE.name, nodeFactory = object : MockNetwork.Factory<MockNetwork.MockNode> {
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceInfo>, id: Int, advertisedServices: Set<ServiceInfo>, id: Int,
overrideServices: Map<ServiceInfo, KeyPair>?, overrideServices: Map<ServiceInfo, KeyPair>?,
@ -126,19 +128,19 @@ class AttachmentTests {
} }
} }
}, advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type))) }, advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type)))
val n1 = mockNet.createNode(n0.network.myAddress) val bobNode = mockNet.createNode(aliceNode.network.myAddress, legalName = BOB.name)
// Ensure that registration was successful before progressing any further // Ensure that registration was successful before progressing any further
mockNet.runNetwork() mockNet.runNetwork()
n0.internals.ensureRegistered() aliceNode.internals.ensureRegistered()
n0.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java) aliceNode.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
n1.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java) bobNode.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
val attachment = fakeAttachment() val attachment = fakeAttachment()
// Insert an attachment into node zero's store directly. // Insert an attachment into node zero's store directly.
val id = n0.database.transaction { val id = aliceNode.database.transaction {
n0.attachments.importAttachment(ByteArrayInputStream(attachment)) aliceNode.attachments.importAttachment(ByteArrayInputStream(attachment))
} }
// Corrupt its store. // Corrupt its store.
@ -146,15 +148,15 @@ class AttachmentTests {
System.arraycopy(corruptBytes, 0, attachment, 0, corruptBytes.size) System.arraycopy(corruptBytes, 0, attachment, 0, corruptBytes.size)
val corruptAttachment = NodeAttachmentService.DBAttachment(attId = id.toString(), content = attachment) val corruptAttachment = NodeAttachmentService.DBAttachment(attId = id.toString(), content = attachment)
n0.database.transaction { aliceNode.database.transaction {
DatabaseTransactionManager.current().session.update(corruptAttachment) DatabaseTransactionManager.current().session.update(corruptAttachment)
} }
// Get n1 to fetch the attachment. Should receive corrupted bytes. // Get n1 to fetch the attachment. Should receive corrupted bytes.
mockNet.runNetwork() mockNet.runNetwork()
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.chooseIdentity()) val bobFlow = bobNode.startAttachmentFlow(setOf(id), aliceNode.info.chooseIdentity())
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith<FetchDataFlow.DownloadedVsRequestedDataMismatch> { f1.resultFuture.getOrThrow() } assertFailsWith<FetchDataFlow.DownloadedVsRequestedDataMismatch> { bobFlow.resultFuture.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

@ -24,24 +24,22 @@ import kotlin.test.assertFailsWith
class CollectSignaturesFlowTests { class CollectSignaturesFlowTests {
lateinit var mockNet: MockNetwork lateinit var mockNet: MockNetwork
lateinit var a: StartedNode<MockNetwork.MockNode> lateinit var aliceNode: StartedNode<MockNetwork.MockNode>
lateinit var b: StartedNode<MockNetwork.MockNode> lateinit var bobNode: StartedNode<MockNetwork.MockNode>
lateinit var c: StartedNode<MockNetwork.MockNode> lateinit var charlieNode: StartedNode<MockNetwork.MockNode>
lateinit var notary: Party lateinit var notary: Party
lateinit var services: MockServices
@Before @Before
fun setup() { fun setup() {
setCordappPackages("net.corda.testing.contracts") setCordappPackages("net.corda.testing.contracts")
services = MockServices()
mockNet = MockNetwork() mockNet = MockNetwork()
val nodes = mockNet.createSomeNodes(3) val notaryNode = mockNet.createNotaryNode()
a = nodes.partyNodes[0] aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
b = nodes.partyNodes[1] bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
c = nodes.partyNodes[2] charlieNode = mockNet.createPartyNode(notaryNode.network.myAddress, CHARLIE.name)
mockNet.runNetwork() mockNet.runNetwork()
notary = a.services.getDefaultNotary() notary = notaryNode.services.getDefaultNotary()
a.internals.ensureRegistered() aliceNode.internals.ensureRegistered()
} }
@After @After
@ -51,7 +49,7 @@ class CollectSignaturesFlowTests {
} }
private fun registerFlowOnAllNodes(flowClass: KClass<out FlowLogic<*>>) { private fun registerFlowOnAllNodes(flowClass: KClass<out FlowLogic<*>>) {
listOf(a, b, c).forEach { listOf(aliceNode, bobNode, charlieNode).forEach {
it.internals.registerInitiatedFlow(flowClass.java) it.internals.registerInitiatedFlow(flowClass.java)
} }
} }
@ -142,18 +140,18 @@ class CollectSignaturesFlowTests {
@Test @Test
fun `successfully collects two signatures`() { fun `successfully collects two signatures`() {
val bConfidentialIdentity = b.database.transaction { val bConfidentialIdentity = bobNode.database.transaction {
b.services.keyManagementService.freshKeyAndCert(b.info.chooseIdentityAndCert(), false) bobNode.services.keyManagementService.freshKeyAndCert(bobNode.info.chooseIdentityAndCert(), false)
} }
a.database.transaction { aliceNode.database.transaction {
// Normally this is handled by TransactionKeyFlow, but here we have to manually let A know about the identity // Normally this is handled by TransactionKeyFlow, but here we have to manually let A know about the identity
a.services.identityService.verifyAndRegisterIdentity(bConfidentialIdentity) aliceNode.services.identityService.verifyAndRegisterIdentity(bConfidentialIdentity)
} }
registerFlowOnAllNodes(TestFlowTwo.Responder::class) registerFlowOnAllNodes(TestFlowTwo.Responder::class)
val magicNumber = 1337 val magicNumber = 1337
val parties = listOf(a.info.chooseIdentity(), bConfidentialIdentity.party, c.info.chooseIdentity()) val parties = listOf(aliceNode.info.chooseIdentity(), bConfidentialIdentity.party, charlieNode.info.chooseIdentity())
val state = DummyContract.MultiOwnerState(magicNumber, parties) val state = DummyContract.MultiOwnerState(magicNumber, parties)
val flow = a.services.startFlow(TestFlowTwo.Initiator(state)) val flow = aliceNode.services.startFlow(TestFlowTwo.Initiator(state))
mockNet.runNetwork() mockNet.runNetwork()
val result = flow.resultFuture.getOrThrow() val result = flow.resultFuture.getOrThrow()
result.verifyRequiredSignatures() result.verifyRequiredSignatures()
@ -163,9 +161,9 @@ class CollectSignaturesFlowTests {
@Test @Test
fun `no need to collect any signatures`() { fun `no need to collect any signatures`() {
val onePartyDummyContract = DummyContract.generateInitial(1337, notary, a.info.chooseIdentity().ref(1)) val onePartyDummyContract = DummyContract.generateInitial(1337, notary, aliceNode.info.chooseIdentity().ref(1))
val ptx = a.services.signInitialTransaction(onePartyDummyContract) val ptx = aliceNode.services.signInitialTransaction(onePartyDummyContract)
val flow = a.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.resultFuture.getOrThrow()
result.verifyRequiredSignatures() result.verifyRequiredSignatures()
@ -175,10 +173,10 @@ class CollectSignaturesFlowTests {
@Test @Test
fun `fails when not signed by initiator`() { fun `fails when not signed by initiator`() {
val onePartyDummyContract = DummyContract.generateInitial(1337, notary, a.info.chooseIdentity().ref(1)) val onePartyDummyContract = DummyContract.generateInitial(1337, notary, aliceNode.info.chooseIdentity().ref(1))
val miniCorpServices = MockServices(MINI_CORP_KEY) val miniCorpServices = MockServices(MINI_CORP_KEY)
val ptx = miniCorpServices.signInitialTransaction(onePartyDummyContract) val ptx = miniCorpServices.signInitialTransaction(onePartyDummyContract)
val flow = a.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.resultFuture.getOrThrow()
@ -188,12 +186,12 @@ class CollectSignaturesFlowTests {
@Test @Test
fun `passes with multiple initial signatures`() { fun `passes with multiple initial signatures`() {
val twoPartyDummyContract = DummyContract.generateInitial(1337, notary, val twoPartyDummyContract = DummyContract.generateInitial(1337, notary,
a.info.chooseIdentity().ref(1), aliceNode.info.chooseIdentity().ref(1),
b.info.chooseIdentity().ref(2), bobNode.info.chooseIdentity().ref(2),
b.info.chooseIdentity().ref(3)) bobNode.info.chooseIdentity().ref(3))
val signedByA = a.services.signInitialTransaction(twoPartyDummyContract) val signedByA = aliceNode.services.signInitialTransaction(twoPartyDummyContract)
val signedByBoth = b.services.addSignature(signedByA) val signedByBoth = bobNode.services.addSignature(signedByA)
val flow = a.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.resultFuture.getOrThrow()
println(result.tx) println(result.tx)

View File

@ -34,8 +34,8 @@ import kotlin.test.assertTrue
class ContractUpgradeFlowTest { class ContractUpgradeFlowTest {
lateinit var mockNet: MockNetwork lateinit var mockNet: MockNetwork
lateinit var a: StartedNode<MockNetwork.MockNode> lateinit var aliceNode: StartedNode<MockNetwork.MockNode>
lateinit var b: StartedNode<MockNetwork.MockNode> lateinit var bobNode: StartedNode<MockNetwork.MockNode>
lateinit var notary: Party lateinit var notary: Party
@Before @Before
@ -43,12 +43,12 @@ class ContractUpgradeFlowTest {
setCordappPackages("net.corda.testing.contracts", "net.corda.finance.contracts.asset", "net.corda.core.flows") setCordappPackages("net.corda.testing.contracts", "net.corda.finance.contracts.asset", "net.corda.core.flows")
mockNet = MockNetwork() mockNet = MockNetwork()
val notaryNode = mockNet.createNotaryNode() val notaryNode = mockNet.createNotaryNode()
a = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name) aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
b = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name) bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
// Process registration // Process registration
mockNet.runNetwork() mockNet.runNetwork()
a.internals.ensureRegistered() aliceNode.internals.ensureRegistered()
notary = notaryNode.services.getDefaultNotary() notary = notaryNode.services.getDefaultNotary()
} }
@ -62,37 +62,37 @@ class ContractUpgradeFlowTest {
@Test @Test
fun `2 parties contract upgrade`() { fun `2 parties contract upgrade`() {
// Create dummy contract. // Create dummy contract.
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, a.info.chooseIdentity().ref(1), b.info.chooseIdentity().ref(1)) val twoPartyDummyContract = DummyContract.generateInitial(0, notary, aliceNode.info.chooseIdentity().ref(1), bobNode.info.chooseIdentity().ref(1))
val signedByA = a.services.signInitialTransaction(twoPartyDummyContract) val signedByA = aliceNode.services.signInitialTransaction(twoPartyDummyContract)
val stx = b.services.addSignature(signedByA) val stx = bobNode.services.addSignature(signedByA)
a.services.startFlow(FinalityFlow(stx, setOf(b.info.chooseIdentity()))) aliceNode.services.startFlow(FinalityFlow(stx, setOf(bobNode.info.chooseIdentity())))
mockNet.runNetwork() mockNet.runNetwork()
val atx = a.database.transaction { a.services.validatedTransactions.getTransaction(stx.id) } val atx = aliceNode.database.transaction { aliceNode.services.validatedTransactions.getTransaction(stx.id) }
val btx = b.database.transaction { b.services.validatedTransactions.getTransaction(stx.id) } val btx = bobNode.database.transaction { bobNode.services.validatedTransactions.getTransaction(stx.id) }
requireNotNull(atx) requireNotNull(atx)
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 = a.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)).resultFuture
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.
b.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)).resultFuture.getOrThrow()
b.services.startFlow(ContractUpgradeFlow.Deauthorise(btx.tx.outRef<ContractState>(0).ref)).resultFuture.getOrThrow() bobNode.services.startFlow(ContractUpgradeFlow.Deauthorise(btx.tx.outRef<ContractState>(0).ref)).resultFuture.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 = a.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)).resultFuture
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
b.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)).resultFuture.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 = a.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)).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
val result = resultFuture.getOrThrow() val result = resultFuture.getOrThrow()
@ -113,8 +113,8 @@ class ContractUpgradeFlowTest {
// Verify outputs. // Verify outputs.
assertTrue(nodeStx!!.tx.outputs.single().data is DummyContractV2.State) assertTrue(nodeStx!!.tx.outputs.single().data is DummyContractV2.State)
} }
check(a) check(aliceNode)
check(b) check(bobNode)
} }
private fun RPCDriverExposedDSLInterface.startProxy(node: StartedNode<*>, user: User): CordaRPCOps { private fun RPCDriverExposedDSLInterface.startProxy(node: StartedNode<*>, user: User): CordaRPCOps {
@ -132,9 +132,9 @@ class ContractUpgradeFlowTest {
fun `2 parties contract upgrade using RPC`() { fun `2 parties contract upgrade using RPC`() {
rpcDriver(initialiseSerialization = false) { rpcDriver(initialiseSerialization = false) {
// Create dummy contract. // Create dummy contract.
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, a.info.chooseIdentity().ref(1), b.info.chooseIdentity().ref(1)) val twoPartyDummyContract = DummyContract.generateInitial(0, notary, aliceNode.info.chooseIdentity().ref(1), bobNode.info.chooseIdentity().ref(1))
val signedByA = a.services.signInitialTransaction(twoPartyDummyContract) val signedByA = aliceNode.services.signInitialTransaction(twoPartyDummyContract)
val stx = b.services.addSignature(signedByA) val stx = bobNode.services.addSignature(signedByA)
val user = rpcTestUser.copy(permissions = setOf( val user = rpcTestUser.copy(permissions = setOf(
startFlowPermission<FinalityInvoker>(), startFlowPermission<FinalityInvoker>(),
@ -142,14 +142,14 @@ class ContractUpgradeFlowTest {
startFlowPermission<ContractUpgradeFlow.Authorise>(), startFlowPermission<ContractUpgradeFlow.Authorise>(),
startFlowPermission<ContractUpgradeFlow.Deauthorise>() startFlowPermission<ContractUpgradeFlow.Deauthorise>()
)) ))
val rpcA = startProxy(a, user) val rpcA = startProxy(aliceNode, user)
val rpcB = startProxy(b, user) val rpcB = startProxy(bobNode, user)
val handle = rpcA.startFlow(::FinalityInvoker, stx, setOf(b.info.chooseIdentity())) val handle = rpcA.startFlow(::FinalityInvoker, stx, setOf(bobNode.info.chooseIdentity()))
mockNet.runNetwork() mockNet.runNetwork()
handle.returnValue.getOrThrow() handle.returnValue.getOrThrow()
val atx = a.database.transaction { a.services.validatedTransactions.getTransaction(stx.id) } val atx = aliceNode.database.transaction { aliceNode.services.validatedTransactions.getTransaction(stx.id) }
val btx = b.database.transaction { b.services.validatedTransactions.getTransaction(stx.id) } val btx = bobNode.database.transaction { bobNode.services.validatedTransactions.getTransaction(stx.id) }
requireNotNull(atx) requireNotNull(atx)
requireNotNull(btx) requireNotNull(btx)
@ -188,12 +188,12 @@ class ContractUpgradeFlowTest {
mockNet.runNetwork() mockNet.runNetwork()
val result = resultFuture.getOrThrow() val result = resultFuture.getOrThrow()
// Check results. // Check results.
listOf(a, b).forEach { listOf(aliceNode, bobNode).forEach {
val signedTX = a.database.transaction { a.services.validatedTransactions.getTransaction(result.ref.txhash) } val signedTX = aliceNode.database.transaction { aliceNode.services.validatedTransactions.getTransaction(result.ref.txhash) }
requireNotNull(signedTX) requireNotNull(signedTX)
// Verify inputs. // Verify inputs.
val input = a.database.transaction { a.services.validatedTransactions.getTransaction(signedTX!!.tx.inputs.single().txhash) } val input = aliceNode.database.transaction { aliceNode.services.validatedTransactions.getTransaction(signedTX!!.tx.inputs.single().txhash) }
requireNotNull(input) requireNotNull(input)
assertTrue(input!!.tx.outputs.single().data is DummyContract.State) assertTrue(input!!.tx.outputs.single().data is DummyContract.State)
@ -206,20 +206,20 @@ class ContractUpgradeFlowTest {
@Test @Test
fun `upgrade Cash to v2`() { fun `upgrade Cash to v2`() {
// Create some cash. // Create some cash.
val chosenIdentity = a.info.chooseIdentity() val chosenIdentity = aliceNode.info.chooseIdentity()
val result = a.services.startFlow(CashIssueFlow(Amount(1000, USD), OpaqueBytes.of(1), notary)).resultFuture val result = aliceNode.services.startFlow(CashIssueFlow(Amount(1000, USD), OpaqueBytes.of(1), notary)).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
val stx = result.getOrThrow().stx val stx = result.getOrThrow().stx
val anonymisedRecipient = result.get().recipient!! val anonymisedRecipient = result.get().recipient!!
val stateAndRef = stx.tx.outRef<Cash.State>(0) val stateAndRef = stx.tx.outRef<Cash.State>(0)
val baseState = a.database.transaction { a.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 = a.services.startFlow(ContractUpgradeFlow.Initiate(stateAndRef, CashV2::class.java)).resultFuture val upgradeResult = aliceNode.services.startFlow(ContractUpgradeFlow.Initiate(stateAndRef, CashV2::class.java)).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
upgradeResult.getOrThrow() upgradeResult.getOrThrow()
// Get contract state from the vault. // Get contract state from the vault.
val firstState = a.database.transaction { a.services.vaultService.queryBy<ContractState>().states.single() } val firstState = aliceNode.database.transaction { aliceNode.services.vaultService.queryBy<ContractState>().states.single() }
assertTrue(firstState.state.data is CashV2.State, "Contract state is upgraded to the new version.") assertTrue(firstState.state.data is CashV2.State, "Contract state is upgraded to the new version.")
assertEquals(Amount(1000000, USD).`issued by`(chosenIdentity.ref(1)), (firstState.state.data as CashV2.State).amount, "Upgraded cash contain the correct amount.") assertEquals(Amount(1000000, USD).`issued by`(chosenIdentity.ref(1)), (firstState.state.data as CashV2.State).amount, "Upgraded cash contain the correct amount.")
assertEquals<Collection<AbstractParty>>(listOf(anonymisedRecipient), (firstState.state.data as CashV2.State).owners, "Upgraded cash belongs to the right owner.") assertEquals<Collection<AbstractParty>>(listOf(anonymisedRecipient), (firstState.state.data as CashV2.State).owners, "Upgraded cash belongs to the right owner.")

View File

@ -7,13 +7,8 @@ import net.corda.finance.POUNDS
import net.corda.finance.contracts.asset.Cash import net.corda.finance.contracts.asset.Cash
import net.corda.finance.issuedBy import net.corda.finance.issuedBy
import net.corda.node.internal.StartedNode import net.corda.node.internal.StartedNode
import net.corda.testing.ALICE import net.corda.testing.*
import net.corda.testing.chooseIdentity
import net.corda.testing.getDefaultNotary
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockServices
import net.corda.testing.setCordappPackages
import net.corda.testing.unsetCordappPackages
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@ -22,21 +17,20 @@ import kotlin.test.assertFailsWith
class FinalityFlowTests { class FinalityFlowTests {
lateinit var mockNet: MockNetwork lateinit var mockNet: MockNetwork
lateinit var nodeA: StartedNode<MockNetwork.MockNode> lateinit var aliceNode: StartedNode<MockNetwork.MockNode>
lateinit var nodeB: StartedNode<MockNetwork.MockNode> lateinit var bobNode: StartedNode<MockNetwork.MockNode>
lateinit var notary: Party lateinit var notary: Party
val services = MockServices()
@Before @Before
fun setup() { fun setup() {
setCordappPackages("net.corda.finance.contracts.asset") setCordappPackages("net.corda.finance.contracts.asset")
mockNet = MockNetwork() mockNet = MockNetwork()
val nodes = mockNet.createSomeNodes(2) val notaryNode = mockNet.createNotaryNode()
nodeA = nodes.partyNodes[0] aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
nodeB = nodes.partyNodes[1] bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
mockNet.runNetwork() mockNet.runNetwork()
nodeA.internals.ensureRegistered() aliceNode.internals.ensureRegistered()
notary = nodeA.services.getDefaultNotary() notary = aliceNode.services.getDefaultNotary()
} }
@After @After
@ -47,28 +41,28 @@ class FinalityFlowTests {
@Test @Test
fun `finalise a simple transaction`() { fun `finalise a simple transaction`() {
val amount = 1000.POUNDS.issuedBy(nodeA.info.chooseIdentity().ref(0)) val amount = 1000.POUNDS.issuedBy(aliceNode.info.chooseIdentity().ref(0))
val builder = TransactionBuilder(notary) val builder = TransactionBuilder(notary)
Cash().generateIssue(builder, amount, nodeB.info.chooseIdentity(), notary) Cash().generateIssue(builder, amount, bobNode.info.chooseIdentity(), notary)
val stx = nodeA.services.signInitialTransaction(builder) val stx = aliceNode.services.signInitialTransaction(builder)
val flow = nodeA.services.startFlow(FinalityFlow(stx)) val flow = aliceNode.services.startFlow(FinalityFlow(stx))
mockNet.runNetwork() mockNet.runNetwork()
val notarisedTx = flow.resultFuture.getOrThrow() val notarisedTx = flow.resultFuture.getOrThrow()
notarisedTx.verifyRequiredSignatures() notarisedTx.verifyRequiredSignatures()
val transactionSeenByB = nodeB.services.database.transaction { val transactionSeenByB = bobNode.services.database.transaction {
nodeB.services.validatedTransactions.getTransaction(notarisedTx.id) bobNode.services.validatedTransactions.getTransaction(notarisedTx.id)
} }
assertEquals(notarisedTx, transactionSeenByB) assertEquals(notarisedTx, transactionSeenByB)
} }
@Test @Test
fun `reject a transaction with unknown parties`() { fun `reject a transaction with unknown parties`() {
val amount = 1000.POUNDS.issuedBy(nodeA.info.chooseIdentity().ref(0)) val amount = 1000.POUNDS.issuedBy(aliceNode.info.chooseIdentity().ref(0))
val fakeIdentity = ALICE // Alice isn't part of this network, so node A won't recognise them val fakeIdentity = CHARLIE // Charlie isn't part of this network, so node A won't recognise them
val builder = TransactionBuilder(notary) val builder = TransactionBuilder(notary)
Cash().generateIssue(builder, amount, fakeIdentity, notary) Cash().generateIssue(builder, amount, fakeIdentity, notary)
val stx = nodeA.services.signInitialTransaction(builder) val stx = aliceNode.services.signInitialTransaction(builder)
val flow = nodeA.services.startFlow(FinalityFlow(stx)) val flow = aliceNode.services.startFlow(FinalityFlow(stx))
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith<IllegalArgumentException> { assertFailsWith<IllegalArgumentException> {
flow.resultFuture.getOrThrow() flow.resultFuture.getOrThrow()

View File

@ -12,7 +12,6 @@ import net.corda.testing.*
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.getDefaultNotary import net.corda.testing.getDefaultNotary
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockServices
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@ -27,25 +26,26 @@ import kotlin.test.assertNull
class ResolveTransactionsFlowTest { class ResolveTransactionsFlowTest {
lateinit var mockNet: MockNetwork lateinit var mockNet: MockNetwork
lateinit var a: StartedNode<MockNetwork.MockNode> lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
lateinit var b: StartedNode<MockNetwork.MockNode> lateinit var megaCorpNode: StartedNode<MockNetwork.MockNode>
lateinit var miniCorpNode: StartedNode<MockNetwork.MockNode>
lateinit var megaCorp: Party
lateinit var miniCorp: Party
lateinit var notary: Party lateinit var notary: Party
lateinit var megaCorpServices: MockServices
lateinit var notaryServices: MockServices
@Before @Before
fun setup() { fun setup() {
setCordappPackages("net.corda.testing.contracts") setCordappPackages("net.corda.testing.contracts")
megaCorpServices = MockServices(MEGA_CORP_KEY)
notaryServices = MockServices(DUMMY_NOTARY_KEY)
mockNet = MockNetwork() mockNet = MockNetwork()
val nodes = mockNet.createSomeNodes() notaryNode = mockNet.createNotaryNode()
a = nodes.partyNodes[0] megaCorpNode = mockNet.createPartyNode(notaryNode.network.myAddress, MEGA_CORP.name)
b = nodes.partyNodes[1] miniCorpNode = mockNet.createPartyNode(notaryNode.network.myAddress, MINI_CORP.name)
a.internals.registerInitiatedFlow(TestResponseFlow::class.java) megaCorpNode.internals.registerInitiatedFlow(TestResponseFlow::class.java)
b.internals.registerInitiatedFlow(TestResponseFlow::class.java) miniCorpNode.internals.registerInitiatedFlow(TestResponseFlow::class.java)
mockNet.runNetwork() mockNet.runNetwork()
notary = a.services.getDefaultNotary() notary = notaryNode.services.getDefaultNotary()
megaCorp = megaCorpNode.info.chooseIdentity()
miniCorp = miniCorpNode.info.chooseIdentity()
} }
@After @After
@ -58,14 +58,14 @@ class ResolveTransactionsFlowTest {
@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), a.info.chooseIdentity()) val p = TestFlow(setOf(stx2.id), megaCorp)
val future = b.services.startFlow(p).resultFuture val future = miniCorpNode.services.startFlow(p).resultFuture
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 })
b.database.transaction { miniCorpNode.database.transaction {
assertEquals(stx1, b.services.validatedTransactions.getTransaction(stx1.id)) assertEquals(stx1, miniCorpNode.services.validatedTransactions.getTransaction(stx1.id))
assertEquals(stx2, b.services.validatedTransactions.getTransaction(stx2.id)) assertEquals(stx2, miniCorpNode.services.validatedTransactions.getTransaction(stx2.id))
} }
} }
// DOCEND 1 // DOCEND 1
@ -73,8 +73,8 @@ class ResolveTransactionsFlowTest {
@Test @Test
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), a.info.chooseIdentity()) val p = TestFlow(setOf(stx.id), megaCorp)
val future = b.services.startFlow(p).resultFuture val future = miniCorpNode.services.startFlow(p).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith(SignedTransaction.SignaturesMissingException::class) { future.getOrThrow() } assertFailsWith(SignedTransaction.SignaturesMissingException::class) { future.getOrThrow() }
} }
@ -82,14 +82,14 @@ class ResolveTransactionsFlowTest {
@Test @Test
fun `resolve from a signed transaction`() { fun `resolve from a signed transaction`() {
val (stx1, stx2) = makeTransactions() val (stx1, stx2) = makeTransactions()
val p = TestFlow(stx2, a.info.chooseIdentity()) val p = TestFlow(stx2, megaCorp)
val future = b.services.startFlow(p).resultFuture val future = miniCorpNode.services.startFlow(p).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() future.getOrThrow()
b.database.transaction { miniCorpNode.database.transaction {
assertEquals(stx1, b.services.validatedTransactions.getTransaction(stx1.id)) assertEquals(stx1, miniCorpNode.services.validatedTransactions.getTransaction(stx1.id))
// But stx2 wasn't inserted, just stx1. // But stx2 wasn't inserted, just stx1.
assertNull(b.services.validatedTransactions.getTransaction(stx2.id)) assertNull(miniCorpNode.services.validatedTransactions.getTransaction(stx2.id))
} }
} }
@ -100,15 +100,15 @@ class ResolveTransactionsFlowTest {
val count = 50 val count = 50
var cursor = stx2 var cursor = stx2
repeat(count) { repeat(count) {
val builder = DummyContract.move(cursor.tx.outRef(0), MINI_CORP) val builder = DummyContract.move(cursor.tx.outRef(0), miniCorp)
val stx = megaCorpServices.signInitialTransaction(builder) val stx = megaCorpNode.services.signInitialTransaction(builder)
a.database.transaction { megaCorpNode.database.transaction {
a.services.recordTransactions(stx) megaCorpNode.services.recordTransactions(stx)
} }
cursor = stx cursor = stx
} }
val p = TestFlow(setOf(cursor.id), a.info.chooseIdentity(), 40) val p = TestFlow(setOf(cursor.id), megaCorp, 40)
val future = b.services.startFlow(p).resultFuture val future = miniCorpNode.services.startFlow(p).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith<ResolveTransactionsFlow.ExcessivelyLargeTransactionGraph> { future.getOrThrow() } assertFailsWith<ResolveTransactionsFlow.ExcessivelyLargeTransactionGraph> { future.getOrThrow() }
} }
@ -117,22 +117,22 @@ class ResolveTransactionsFlowTest {
fun `triangle of transactions resolves fine`() { fun `triangle of transactions resolves fine`() {
val stx1 = makeTransactions().first val stx1 = makeTransactions().first
val stx2 = DummyContract.move(stx1.tx.outRef(0), MINI_CORP).run { val stx2 = DummyContract.move(stx1.tx.outRef(0), miniCorp).let { builder ->
val ptx = megaCorpServices.signInitialTransaction(this) val ptx = megaCorpNode.services.signInitialTransaction(builder)
notaryServices.addSignature(ptx) notaryNode.services.addSignature(ptx, notary.owningKey)
} }
val stx3 = DummyContract.move(listOf(stx1.tx.outRef(0), stx2.tx.outRef(0)), MINI_CORP).run { val stx3 = DummyContract.move(listOf(stx1.tx.outRef(0), stx2.tx.outRef(0)), miniCorp).let { builder ->
val ptx = megaCorpServices.signInitialTransaction(this) val ptx = megaCorpNode.services.signInitialTransaction(builder)
notaryServices.addSignature(ptx) notaryNode.services.addSignature(ptx, notary.owningKey)
} }
a.database.transaction { megaCorpNode.database.transaction {
a.services.recordTransactions(stx2, stx3) megaCorpNode.services.recordTransactions(stx2, stx3)
} }
val p = TestFlow(setOf(stx3.id), a.info.chooseIdentity()) val p = TestFlow(setOf(stx3.id), megaCorp)
val future = b.services.startFlow(p).resultFuture val future = miniCorpNode.services.startFlow(p).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() future.getOrThrow()
} }
@ -149,43 +149,43 @@ class ResolveTransactionsFlowTest {
return bs.toByteArray().sequence().open() return bs.toByteArray().sequence().open()
} }
// TODO: this operation should not require an explicit transaction // TODO: this operation should not require an explicit transaction
val id = a.database.transaction { val id = megaCorpNode.database.transaction {
a.services.attachments.importAttachment(makeJar()) megaCorpNode.services.attachments.importAttachment(makeJar())
} }
val stx2 = makeTransactions(withAttachment = id).second val stx2 = makeTransactions(withAttachment = id).second
val p = TestFlow(stx2, a.info.chooseIdentity()) val p = TestFlow(stx2, megaCorp)
val future = b.services.startFlow(p).resultFuture val future = miniCorpNode.services.startFlow(p).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() future.getOrThrow()
// TODO: this operation should not require an explicit transaction // TODO: this operation should not require an explicit transaction
b.database.transaction { miniCorpNode.database.transaction {
assertNotNull(b.services.attachments.openAttachment(id)) assertNotNull(miniCorpNode.services.attachments.openAttachment(id))
} }
} }
// DOCSTART 2 // DOCSTART 2
private fun makeTransactions(signFirstTX: Boolean = true, withAttachment: SecureHash? = null): Pair<SignedTransaction, SignedTransaction> { private fun makeTransactions(signFirstTX: Boolean = true, withAttachment: SecureHash? = null): Pair<SignedTransaction, SignedTransaction> {
// Make a chain of custody of dummy states and insert into node A. // Make a chain of custody of dummy states and insert into node A.
val dummy1: SignedTransaction = DummyContract.generateInitial(0, notary, MEGA_CORP.ref(1)).let { val dummy1: SignedTransaction = DummyContract.generateInitial(0, notary, megaCorp.ref(1)).let {
if (withAttachment != null) if (withAttachment != null)
it.addAttachment(withAttachment) it.addAttachment(withAttachment)
when (signFirstTX) { when (signFirstTX) {
true -> { true -> {
val ptx = megaCorpServices.signInitialTransaction(it) val ptx = megaCorpNode.services.signInitialTransaction(it)
notaryServices.addSignature(ptx) notaryNode.services.addSignature(ptx, notary.owningKey)
} }
false -> { false -> {
notaryServices.signInitialTransaction(it) notaryNode.services.signInitialTransaction(it, notary.owningKey)
} }
} }
} }
val dummy2: SignedTransaction = DummyContract.move(dummy1.tx.outRef(0), MINI_CORP).let { val dummy2: SignedTransaction = DummyContract.move(dummy1.tx.outRef(0), miniCorp).let {
val ptx = megaCorpServices.signInitialTransaction(it) val ptx = megaCorpNode.services.signInitialTransaction(it)
notaryServices.addSignature(ptx) notaryNode.services.addSignature(ptx, notary.owningKey)
} }
a.database.transaction { megaCorpNode.database.transaction {
a.services.recordTransactions(dummy1, dummy2) megaCorpNode.services.recordTransactions(dummy1, dummy2)
} }
return Pair(dummy1, dummy2) return Pair(dummy1, dummy2)
} }

View File

@ -7,13 +7,10 @@ import net.corda.finance.DOLLARS
import net.corda.finance.`issued by` import net.corda.finance.`issued by`
import net.corda.finance.contracts.asset.Cash import net.corda.finance.contracts.asset.Cash
import net.corda.node.internal.StartedNode import net.corda.node.internal.StartedNode
import net.corda.testing.chooseIdentity import net.corda.testing.*
import net.corda.testing.getDefaultNotary
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetwork.MockNode import net.corda.testing.node.MockNetwork.MockNode
import net.corda.testing.setCordappPackages
import net.corda.testing.unsetCordappPackages
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@ -33,9 +30,9 @@ class CashExitFlowTests {
fun start() { fun start() {
setCordappPackages("net.corda.finance.contracts.asset") setCordappPackages("net.corda.finance.contracts.asset")
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin()) mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin())
val nodes = mockNet.createSomeNodes(1) notaryNode = mockNet.createNotaryNode()
notaryNode = nodes.notaryNode bankOfCordaNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
bankOfCordaNode = nodes.partyNodes[0] notary = notaryNode.services.getDefaultNotary()
bankOfCorda = bankOfCordaNode.info.chooseIdentity() bankOfCorda = bankOfCordaNode.info.chooseIdentity()
mockNet.runNetwork() mockNet.runNetwork()

View File

@ -9,6 +9,8 @@ import net.corda.finance.contracts.asset.Cash
import net.corda.node.internal.StartedNode import net.corda.node.internal.StartedNode
import net.corda.testing.chooseIdentity import net.corda.testing.chooseIdentity
import net.corda.testing.getDefaultNotary import net.corda.testing.getDefaultNotary
import net.corda.testing.BOC
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetwork.MockNode import net.corda.testing.node.MockNetwork.MockNode
@ -30,13 +32,11 @@ class CashIssueFlowTests {
fun start() { fun start() {
setCordappPackages("net.corda.finance.contracts.asset") setCordappPackages("net.corda.finance.contracts.asset")
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin()) mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin())
val nodes = mockNet.createSomeNodes(1) notaryNode = mockNet.createNotaryNode()
notaryNode = nodes.notaryNode bankOfCordaNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
bankOfCordaNode = nodes.partyNodes[0]
bankOfCorda = bankOfCordaNode.info.chooseIdentity() bankOfCorda = bankOfCordaNode.info.chooseIdentity()
notary = notaryNode.services.getDefaultNotary()
mockNet.runNetwork() mockNet.runNetwork()
notary = bankOfCordaNode.services.getDefaultNotary()
} }
@After @After

View File

@ -33,9 +33,8 @@ class CashPaymentFlowTests {
fun start() { fun start() {
setCordappPackages("net.corda.finance.contracts.asset") setCordappPackages("net.corda.finance.contracts.asset")
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin()) mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin())
val nodes = mockNet.createSomeNodes(1) notaryNode = mockNet.createNotaryNode()
notaryNode = nodes.notaryNode bankOfCordaNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
bankOfCordaNode = nodes.partyNodes[0]
bankOfCorda = bankOfCordaNode.info.chooseIdentity() bankOfCorda = bankOfCordaNode.info.chooseIdentity()
notary = notaryNode.services.getDefaultNotary() notary = notaryNode.services.getDefaultNotary()
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture

View File

@ -93,15 +93,13 @@ class TwoPartyTradeFlowTests {
mockNet = MockNetwork(false, true) mockNet = MockNetwork(false, true)
ledger(initialiseSerialization = false) { ledger(initialiseSerialization = false) {
val basketOfNodes = mockNet.createSomeNodes(3) val notaryNode = mockNet.createNotaryNode()
val notaryNode = basketOfNodes.notaryNode val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val aliceNode = basketOfNodes.partyNodes[0] val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val bobNode = basketOfNodes.partyNodes[1] val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
val bankNode = basketOfNodes.partyNodes[2] val notary = notaryNode.services.getDefaultNotary()
val cashIssuer = bankNode.info.chooseIdentity().ref(1) val cashIssuer = bankNode.info.chooseIdentity().ref(1)
val cpIssuer = bankNode.info.chooseIdentity().ref(1, 2, 3) val cpIssuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
val notary = aliceNode.services.getDefaultNotary()
aliceNode.internals.disableDBCloseOnStop() aliceNode.internals.disableDBCloseOnStop()
bobNode.internals.disableDBCloseOnStop() bobNode.internals.disableDBCloseOnStop()
@ -144,7 +142,7 @@ class TwoPartyTradeFlowTests {
mockNet = MockNetwork(false, true) mockNet = MockNetwork(false, true)
ledger(initialiseSerialization = false) { ledger(initialiseSerialization = false) {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name) val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name) val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
@ -198,7 +196,7 @@ class TwoPartyTradeFlowTests {
fun `shutdown and restore`() { fun `shutdown and restore`() {
mockNet = MockNetwork(false) mockNet = MockNetwork(false)
ledger(initialiseSerialization = false) { ledger(initialiseSerialization = false) {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
var bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name) var bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name) val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
@ -332,7 +330,7 @@ class TwoPartyTradeFlowTests {
fun `check dependencies of sale asset are resolved`() { fun `check dependencies of sale asset are resolved`() {
mockNet = MockNetwork(false) mockNet = MockNetwork(false)
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode()
val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name) val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name) val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
val bankNode = makeNodeWithTracking(notaryNode.network.myAddress, BOC.name) val bankNode = makeNodeWithTracking(notaryNode.network.myAddress, BOC.name)
@ -439,7 +437,7 @@ class TwoPartyTradeFlowTests {
fun `track works`() { fun `track works`() {
mockNet = MockNetwork(false) mockNet = MockNetwork(false)
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode()
val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name) val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name) val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
val bankNode = makeNodeWithTracking(notaryNode.network.myAddress, BOC.name) val bankNode = makeNodeWithTracking(notaryNode.network.myAddress, BOC.name)
@ -596,7 +594,7 @@ class TwoPartyTradeFlowTests {
aliceError: Boolean, aliceError: Boolean,
expectedMessageSubstring: String expectedMessageSubstring: String
) { ) {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name) val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name) val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)

View File

@ -5,6 +5,7 @@ import net.corda.core.utilities.getOrThrow
import net.corda.nodeapi.internal.ServiceInfo import net.corda.nodeapi.internal.ServiceInfo
import net.corda.testing.ALICE import net.corda.testing.ALICE
import net.corda.testing.BOB import net.corda.testing.BOB
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
@ -29,10 +30,9 @@ class NetworkMapCacheTest {
@Test @Test
fun registerWithNetwork() { fun registerWithNetwork() {
val nodes = mockNet.createSomeNodes(1) val mapNode = mockNet.createNotaryNode()
val n0 = nodes.mapNode val aliceNode = mockNet.createPartyNode(mapNode.network.myAddress, ALICE.name)
val n1 = nodes.partyNodes[0] val future = aliceNode.services.networkMapCache.addMapService(aliceNode.network, mapNode.network.myAddress, false, null)
val future = n1.services.networkMapCache.addMapService(n1.network, n0.network.myAddress, false, null)
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() future.getOrThrow()
} }
@ -40,30 +40,29 @@ class NetworkMapCacheTest {
@Test @Test
fun `key collision`() { fun `key collision`() {
val entropy = BigInteger.valueOf(24012017L) val entropy = BigInteger.valueOf(24012017L)
val nodeA = mockNet.createNode(nodeFactory = MockNetwork.DefaultFactory, legalName = ALICE.name, entropyRoot = entropy, advertisedServices = ServiceInfo(NetworkMapService.type)) val aliceNode = mockNet.createNode(nodeFactory = MockNetwork.DefaultFactory, legalName = ALICE.name, entropyRoot = entropy, advertisedServices = ServiceInfo(NetworkMapService.type))
val nodeB = mockNet.createNode(nodeFactory = MockNetwork.DefaultFactory, legalName = BOB.name, entropyRoot = entropy, advertisedServices = ServiceInfo(NetworkMapService.type)) val bobNode = mockNet.createNode(nodeFactory = MockNetwork.DefaultFactory, legalName = BOB.name, entropyRoot = entropy, advertisedServices = ServiceInfo(NetworkMapService.type))
assertEquals(nodeA.info.chooseIdentity(), nodeB.info.chooseIdentity()) assertEquals(aliceNode.info.chooseIdentity(), bobNode.info.chooseIdentity())
mockNet.runNetwork() mockNet.runNetwork()
// Node A currently knows only about itself, so this returns node A // Node A currently knows only about itself, so this returns node A
assertEquals(nodeA.services.networkMapCache.getNodesByLegalIdentityKey(nodeA.info.chooseIdentity().owningKey).singleOrNull(), nodeA.info) assertEquals(aliceNode.services.networkMapCache.getNodesByLegalIdentityKey(aliceNode.info.chooseIdentity().owningKey).singleOrNull(), aliceNode.info)
nodeA.services.networkMapCache.addNode(nodeB.info) aliceNode.services.networkMapCache.addNode(bobNode.info)
// The details of node B write over those for node A // The details of node B write over those for node A
assertEquals(nodeA.services.networkMapCache.getNodesByLegalIdentityKey(nodeA.info.chooseIdentity().owningKey).singleOrNull(), nodeB.info) assertEquals(aliceNode.services.networkMapCache.getNodesByLegalIdentityKey(aliceNode.info.chooseIdentity().owningKey).singleOrNull(), bobNode.info)
} }
@Test @Test
fun `getNodeByLegalIdentity`() { fun `getNodeByLegalIdentity`() {
val nodes = mockNet.createSomeNodes(1) val notaryNode = mockNet.createNotaryNode()
val n0 = nodes.mapNode val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val n1 = nodes.partyNodes[0] val notaryCache: NetworkMapCache = notaryNode.services.networkMapCache
val node0Cache: NetworkMapCache = n0.services.networkMapCache val expected = aliceNode.info
val expected = n1.info
mockNet.runNetwork() mockNet.runNetwork()
val actual = n0.database.transaction { node0Cache.getNodeByLegalIdentity(n1.info.chooseIdentity()) } val actual = notaryNode.database.transaction { notaryCache.getNodeByLegalIdentity(aliceNode.info.chooseIdentity()) }
assertEquals(expected, actual) assertEquals(expected, actual)
// TODO: Should have a test case with anonymous lookup // TODO: Should have a test case with anonymous lookup
@ -71,19 +70,18 @@ class NetworkMapCacheTest {
@Test @Test
fun `remove node from cache`() { fun `remove node from cache`() {
val nodes = mockNet.createSomeNodes(1) val notaryNode = mockNet.createNotaryNode()
val n0 = nodes.mapNode val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val n1 = nodes.partyNodes[0] val notaryLegalIdentity = notaryNode.info.chooseIdentity()
val n0Identity = n0.info.chooseIdentity() val alice = aliceNode.info.chooseIdentity()
val n1Identity = n1.info.chooseIdentity() val notaryCache = notaryNode.services.networkMapCache as PersistentNetworkMapCache
val node0Cache = n0.services.networkMapCache as PersistentNetworkMapCache
mockNet.runNetwork() mockNet.runNetwork()
n0.database.transaction { notaryNode.database.transaction {
assertThat(node0Cache.getNodeByLegalIdentity(n1Identity) != null) assertThat(notaryCache.getNodeByLegalIdentity(alice) != null)
node0Cache.removeNode(n1.info) notaryCache.removeNode(aliceNode.info)
assertThat(node0Cache.getNodeByLegalIdentity(n1Identity) == null) assertThat(notaryCache.getNodeByLegalIdentity(alice) == null)
assertThat(node0Cache.getNodeByLegalIdentity(n0Identity) != null) assertThat(notaryCache.getNodeByLegalIdentity(notaryLegalIdentity) != null)
assertThat(node0Cache.getNodeByLegalName(n1Identity.name) == null) assertThat(notaryCache.getNodeByLegalName(alice.name) == null)
} }
} }
} }

View File

@ -379,31 +379,9 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
} }
/** /**
* A bundle that separates the generic user nodes and service-providing nodes. A real network might not be so * Construct a default notary node.
* clearly separated, but this is convenient for testing.
*/ */
data class BasketOfNodes(val partyNodes: List<StartedNode<MockNode>>, val notaryNode: StartedNode<MockNode>, val mapNode: StartedNode<MockNode>) fun createNotaryNode() = createNotaryNode(null, DUMMY_NOTARY.name, null, null)
/**
* Sets up a network with the requested number of nodes (defaulting to two), with one or more service nodes that
* run a notary, network map, any oracles etc.
*/
@JvmOverloads
fun createSomeNodes(numPartyNodes: Int = 2, nodeFactory: Factory<*> = defaultFactory, notaryKeyPair: KeyPair? = DUMMY_NOTARY_KEY): BasketOfNodes {
require(nodes.isEmpty())
val notaryServiceInfo = ServiceInfo(ValidatingNotaryService.type)
val notaryOverride = if (notaryKeyPair != null)
mapOf(Pair(notaryServiceInfo, notaryKeyPair))
else
null
val mapNode = createNode(nodeFactory = nodeFactory, advertisedServices = ServiceInfo(NetworkMapService.type))
val mapAddress = mapNode.network.myAddress
val notaryNode = createNode(mapAddress, nodeFactory = nodeFactory, overrideServices = notaryOverride, advertisedServices = notaryServiceInfo)
val nodes = (1..numPartyNodes).map {
createPartyNode(mapAddress)
}
return BasketOfNodes(nodes, notaryNode, mapNode)
}
fun createNotaryNode(networkMapAddress: SingleMessageRecipient? = null, fun createNotaryNode(networkMapAddress: SingleMessageRecipient? = null,
legalName: CordaX500Name? = null, legalName: CordaX500Name? = null,
@ -413,6 +391,10 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type, serviceName))) advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type, serviceName)))
} }
// Convenience method for Java
fun createPartyNode(networkMapAddress: SingleMessageRecipient,
legalName: CordaX500Name) = createPartyNode(networkMapAddress, legalName, null)
fun createPartyNode(networkMapAddress: SingleMessageRecipient, fun createPartyNode(networkMapAddress: SingleMessageRecipient,
legalName: CordaX500Name? = null, legalName: CordaX500Name? = null,
overrideServices: Map<ServiceInfo, KeyPair>? = null): StartedNode<MockNode> { overrideServices: Map<ServiceInfo, KeyPair>? = null): StartedNode<MockNode> {