mirror of
https://github.com/corda/corda.git
synced 2025-01-18 10:46:38 +00:00
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:
parent
5e5f9d7790
commit
2aaeb4c0b5
@ -40,7 +40,7 @@ class IdentitySyncFlowTests {
|
||||
@Test
|
||||
fun `sync confidential identities`() {
|
||||
// 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 bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
val alice: Party = aliceNode.services.myInfo.chooseIdentity()
|
||||
|
@ -22,7 +22,7 @@ class SwapIdentitiesFlowTests {
|
||||
val mockNet = MockNetwork(false, true)
|
||||
|
||||
// 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 bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
val alice: Party = aliceNode.services.myInfo.chooseIdentity()
|
||||
|
@ -5,6 +5,7 @@ import com.google.common.primitives.Primitives;
|
||||
import net.corda.core.identity.Party;
|
||||
import net.corda.node.internal.StartedNode;
|
||||
import net.corda.testing.node.MockNetwork;
|
||||
import net.corda.testing.TestConstants;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@ -19,17 +20,18 @@ import static org.junit.Assert.fail;
|
||||
public class FlowsInJavaTest {
|
||||
|
||||
private final MockNetwork mockNet = new MockNetwork();
|
||||
private StartedNode<MockNetwork.MockNode> node1;
|
||||
private StartedNode<MockNetwork.MockNode> node2;
|
||||
private StartedNode<MockNetwork.MockNode> notaryNode;
|
||||
private StartedNode<MockNetwork.MockNode> aliceNode;
|
||||
private StartedNode<MockNetwork.MockNode> bobNode;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockNetwork.BasketOfNodes someNodes = mockNet.createSomeNodes(2);
|
||||
node1 = someNodes.getPartyNodes().get(0);
|
||||
node2 = someNodes.getPartyNodes().get(1);
|
||||
notaryNode = mockNet.createNotaryNode();
|
||||
aliceNode = mockNet.createPartyNode(notaryNode.getNetwork().getMyAddress(), TestConstants.getALICE().getName());
|
||||
bobNode = mockNet.createPartyNode(notaryNode.getNetwork().getMyAddress(), TestConstants.getBOB().getName());
|
||||
mockNet.runNetwork();
|
||||
// Ensure registration was successful
|
||||
node1.getInternals().getNodeReadyFuture().get();
|
||||
aliceNode.getInternals().getNodeReadyFuture().get();
|
||||
}
|
||||
|
||||
@After
|
||||
@ -39,8 +41,8 @@ public class FlowsInJavaTest {
|
||||
|
||||
@Test
|
||||
public void suspendableActionInsideUnwrap() throws Exception {
|
||||
node2.getInternals().registerInitiatedFlow(SendHelloAndThenReceive.class);
|
||||
Future<String> result = node1.getServices().startFlow(new SendInUnwrapFlow(chooseIdentity(node2.getInfo()))).getResultFuture();
|
||||
bobNode.getInternals().registerInitiatedFlow(SendHelloAndThenReceive.class);
|
||||
Future<String> result = aliceNode.getServices().startFlow(new SendInUnwrapFlow(chooseIdentity(bobNode.getInfo()))).getResultFuture();
|
||||
mockNet.runNetwork();
|
||||
assertThat(result.get()).isEqualTo("Hello");
|
||||
}
|
||||
@ -55,8 +57,8 @@ public class FlowsInJavaTest {
|
||||
}
|
||||
|
||||
private void primitiveReceiveTypeTest(Class<?> receiveType) throws InterruptedException {
|
||||
PrimitiveReceiveFlow flow = new PrimitiveReceiveFlow(chooseIdentity(node2.getInfo()), receiveType);
|
||||
Future<?> result = node1.getServices().startFlow(flow).getResultFuture();
|
||||
PrimitiveReceiveFlow flow = new PrimitiveReceiveFlow(chooseIdentity(bobNode.getInfo()), receiveType);
|
||||
Future<?> result = aliceNode.getServices().startFlow(flow).getResultFuture();
|
||||
mockNet.runNetwork();
|
||||
try {
|
||||
result.get();
|
||||
|
@ -10,12 +10,14 @@ import net.corda.core.internal.FetchDataFlow
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.nodeapi.internal.ServiceInfo
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.persistence.NodeAttachmentService
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
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.node.MockNetwork
|
||||
import org.junit.After
|
||||
@ -55,68 +57,68 @@ class AttachmentTests {
|
||||
|
||||
@Test
|
||||
fun `download and store`() {
|
||||
val nodes = mockNet.createSomeNodes(2)
|
||||
val n0 = nodes.partyNodes[0]
|
||||
val n1 = nodes.partyNodes[1]
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
|
||||
// Ensure that registration was successful before progressing any further
|
||||
mockNet.runNetwork()
|
||||
n0.internals.ensureRegistered()
|
||||
aliceNode.internals.ensureRegistered()
|
||||
|
||||
n0.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
||||
n1.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
||||
aliceNode.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
||||
bobNode.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
||||
|
||||
// Insert an attachment into node zero's store directly.
|
||||
val id = n0.database.transaction {
|
||||
n0.attachments.importAttachment(ByteArrayInputStream(fakeAttachment()))
|
||||
val id = aliceNode.database.transaction {
|
||||
aliceNode.attachments.importAttachment(ByteArrayInputStream(fakeAttachment()))
|
||||
}
|
||||
|
||||
// Get node one to run a flow to fetch it and insert it.
|
||||
mockNet.runNetwork()
|
||||
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.chooseIdentity())
|
||||
val bobFlow = bobNode.startAttachmentFlow(setOf(id), aliceNode.info.chooseIdentity())
|
||||
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.
|
||||
val attachment = n1.database.transaction {
|
||||
n1.attachments.openAttachment(id)!!
|
||||
val attachment = bobNode.database.transaction {
|
||||
bobNode.attachments.openAttachment(id)!!
|
||||
}
|
||||
|
||||
assertEquals(id, attachment.open().readBytes().sha256())
|
||||
|
||||
// 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])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `missing`() {
|
||||
val nodes = mockNet.createSomeNodes(2)
|
||||
val n0 = nodes.partyNodes[0]
|
||||
val n1 = nodes.partyNodes[1]
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
|
||||
// Ensure that registration was successful before progressing any further
|
||||
mockNet.runNetwork()
|
||||
n0.internals.ensureRegistered()
|
||||
aliceNode.internals.ensureRegistered()
|
||||
|
||||
n0.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
||||
n1.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
||||
aliceNode.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
||||
bobNode.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
||||
|
||||
// Get node one to fetch a non-existent attachment.
|
||||
val hash = SecureHash.randomSHA256()
|
||||
mockNet.runNetwork()
|
||||
val f1 = n1.startAttachmentFlow(setOf(hash), n0.info.chooseIdentity())
|
||||
val bobFlow = bobNode.startAttachmentFlow(setOf(hash), aliceNode.info.chooseIdentity())
|
||||
mockNet.runNetwork()
|
||||
val e = assertFailsWith<FetchDataFlow.HashNotFound> { f1.resultFuture.getOrThrow() }
|
||||
val e = assertFailsWith<FetchDataFlow.HashNotFound> { bobFlow.resultFuture.getOrThrow() }
|
||||
assertEquals(hash, e.requested)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `malicious response`() {
|
||||
// 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?,
|
||||
advertisedServices: Set<ServiceInfo>, id: Int,
|
||||
overrideServices: Map<ServiceInfo, KeyPair>?,
|
||||
@ -126,19 +128,19 @@ class AttachmentTests {
|
||||
}
|
||||
}
|
||||
}, 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
|
||||
mockNet.runNetwork()
|
||||
n0.internals.ensureRegistered()
|
||||
aliceNode.internals.ensureRegistered()
|
||||
|
||||
n0.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
||||
n1.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
||||
aliceNode.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
||||
bobNode.internals.registerInitiatedFlow(FetchAttachmentsResponse::class.java)
|
||||
|
||||
val attachment = fakeAttachment()
|
||||
// Insert an attachment into node zero's store directly.
|
||||
val id = n0.database.transaction {
|
||||
n0.attachments.importAttachment(ByteArrayInputStream(attachment))
|
||||
val id = aliceNode.database.transaction {
|
||||
aliceNode.attachments.importAttachment(ByteArrayInputStream(attachment))
|
||||
}
|
||||
|
||||
// Corrupt its store.
|
||||
@ -146,15 +148,15 @@ class AttachmentTests {
|
||||
System.arraycopy(corruptBytes, 0, attachment, 0, corruptBytes.size)
|
||||
|
||||
val corruptAttachment = NodeAttachmentService.DBAttachment(attId = id.toString(), content = attachment)
|
||||
n0.database.transaction {
|
||||
aliceNode.database.transaction {
|
||||
DatabaseTransactionManager.current().session.update(corruptAttachment)
|
||||
}
|
||||
|
||||
// Get n1 to fetch the attachment. Should receive corrupted bytes.
|
||||
mockNet.runNetwork()
|
||||
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.chooseIdentity())
|
||||
val bobFlow = bobNode.startAttachmentFlow(setOf(id), aliceNode.info.chooseIdentity())
|
||||
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))
|
||||
|
@ -24,24 +24,22 @@ import kotlin.test.assertFailsWith
|
||||
|
||||
class CollectSignaturesFlowTests {
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var a: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var b: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var c: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var aliceNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var bobNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var charlieNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var notary: Party
|
||||
lateinit var services: MockServices
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
setCordappPackages("net.corda.testing.contracts")
|
||||
services = MockServices()
|
||||
mockNet = MockNetwork()
|
||||
val nodes = mockNet.createSomeNodes(3)
|
||||
a = nodes.partyNodes[0]
|
||||
b = nodes.partyNodes[1]
|
||||
c = nodes.partyNodes[2]
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
charlieNode = mockNet.createPartyNode(notaryNode.network.myAddress, CHARLIE.name)
|
||||
mockNet.runNetwork()
|
||||
notary = a.services.getDefaultNotary()
|
||||
a.internals.ensureRegistered()
|
||||
notary = notaryNode.services.getDefaultNotary()
|
||||
aliceNode.internals.ensureRegistered()
|
||||
}
|
||||
|
||||
@After
|
||||
@ -51,7 +49,7 @@ class CollectSignaturesFlowTests {
|
||||
}
|
||||
|
||||
private fun registerFlowOnAllNodes(flowClass: KClass<out FlowLogic<*>>) {
|
||||
listOf(a, b, c).forEach {
|
||||
listOf(aliceNode, bobNode, charlieNode).forEach {
|
||||
it.internals.registerInitiatedFlow(flowClass.java)
|
||||
}
|
||||
}
|
||||
@ -142,18 +140,18 @@ class CollectSignaturesFlowTests {
|
||||
|
||||
@Test
|
||||
fun `successfully collects two signatures`() {
|
||||
val bConfidentialIdentity = b.database.transaction {
|
||||
b.services.keyManagementService.freshKeyAndCert(b.info.chooseIdentityAndCert(), false)
|
||||
val bConfidentialIdentity = bobNode.database.transaction {
|
||||
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
|
||||
a.services.identityService.verifyAndRegisterIdentity(bConfidentialIdentity)
|
||||
aliceNode.services.identityService.verifyAndRegisterIdentity(bConfidentialIdentity)
|
||||
}
|
||||
registerFlowOnAllNodes(TestFlowTwo.Responder::class)
|
||||
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 flow = a.services.startFlow(TestFlowTwo.Initiator(state))
|
||||
val flow = aliceNode.services.startFlow(TestFlowTwo.Initiator(state))
|
||||
mockNet.runNetwork()
|
||||
val result = flow.resultFuture.getOrThrow()
|
||||
result.verifyRequiredSignatures()
|
||||
@ -163,9 +161,9 @@ class CollectSignaturesFlowTests {
|
||||
|
||||
@Test
|
||||
fun `no need to collect any signatures`() {
|
||||
val onePartyDummyContract = DummyContract.generateInitial(1337, notary, a.info.chooseIdentity().ref(1))
|
||||
val ptx = a.services.signInitialTransaction(onePartyDummyContract)
|
||||
val flow = a.services.startFlow(CollectSignaturesFlow(ptx, emptySet()))
|
||||
val onePartyDummyContract = DummyContract.generateInitial(1337, notary, aliceNode.info.chooseIdentity().ref(1))
|
||||
val ptx = aliceNode.services.signInitialTransaction(onePartyDummyContract)
|
||||
val flow = aliceNode.services.startFlow(CollectSignaturesFlow(ptx, emptySet()))
|
||||
mockNet.runNetwork()
|
||||
val result = flow.resultFuture.getOrThrow()
|
||||
result.verifyRequiredSignatures()
|
||||
@ -175,10 +173,10 @@ class CollectSignaturesFlowTests {
|
||||
|
||||
@Test
|
||||
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 ptx = miniCorpServices.signInitialTransaction(onePartyDummyContract)
|
||||
val flow = a.services.startFlow(CollectSignaturesFlow(ptx, emptySet()))
|
||||
val flow = aliceNode.services.startFlow(CollectSignaturesFlow(ptx, emptySet()))
|
||||
mockNet.runNetwork()
|
||||
assertFailsWith<IllegalArgumentException>("The Initiator of CollectSignaturesFlow must have signed the transaction.") {
|
||||
flow.resultFuture.getOrThrow()
|
||||
@ -188,12 +186,12 @@ class CollectSignaturesFlowTests {
|
||||
@Test
|
||||
fun `passes with multiple initial signatures`() {
|
||||
val twoPartyDummyContract = DummyContract.generateInitial(1337, notary,
|
||||
a.info.chooseIdentity().ref(1),
|
||||
b.info.chooseIdentity().ref(2),
|
||||
b.info.chooseIdentity().ref(3))
|
||||
val signedByA = a.services.signInitialTransaction(twoPartyDummyContract)
|
||||
val signedByBoth = b.services.addSignature(signedByA)
|
||||
val flow = a.services.startFlow(CollectSignaturesFlow(signedByBoth, emptySet()))
|
||||
aliceNode.info.chooseIdentity().ref(1),
|
||||
bobNode.info.chooseIdentity().ref(2),
|
||||
bobNode.info.chooseIdentity().ref(3))
|
||||
val signedByA = aliceNode.services.signInitialTransaction(twoPartyDummyContract)
|
||||
val signedByBoth = bobNode.services.addSignature(signedByA)
|
||||
val flow = aliceNode.services.startFlow(CollectSignaturesFlow(signedByBoth, emptySet()))
|
||||
mockNet.runNetwork()
|
||||
val result = flow.resultFuture.getOrThrow()
|
||||
println(result.tx)
|
||||
|
@ -34,8 +34,8 @@ import kotlin.test.assertTrue
|
||||
|
||||
class ContractUpgradeFlowTest {
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var a: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var b: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var aliceNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var bobNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var notary: Party
|
||||
|
||||
@Before
|
||||
@ -43,12 +43,12 @@ class ContractUpgradeFlowTest {
|
||||
setCordappPackages("net.corda.testing.contracts", "net.corda.finance.contracts.asset", "net.corda.core.flows")
|
||||
mockNet = MockNetwork()
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
a = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
b = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
|
||||
// Process registration
|
||||
mockNet.runNetwork()
|
||||
a.internals.ensureRegistered()
|
||||
aliceNode.internals.ensureRegistered()
|
||||
|
||||
notary = notaryNode.services.getDefaultNotary()
|
||||
}
|
||||
@ -62,37 +62,37 @@ class ContractUpgradeFlowTest {
|
||||
@Test
|
||||
fun `2 parties contract upgrade`() {
|
||||
// Create dummy contract.
|
||||
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, a.info.chooseIdentity().ref(1), b.info.chooseIdentity().ref(1))
|
||||
val signedByA = a.services.signInitialTransaction(twoPartyDummyContract)
|
||||
val stx = b.services.addSignature(signedByA)
|
||||
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, aliceNode.info.chooseIdentity().ref(1), bobNode.info.chooseIdentity().ref(1))
|
||||
val signedByA = aliceNode.services.signInitialTransaction(twoPartyDummyContract)
|
||||
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()
|
||||
|
||||
val atx = a.database.transaction { a.services.validatedTransactions.getTransaction(stx.id) }
|
||||
val btx = b.database.transaction { b.services.validatedTransactions.getTransaction(stx.id) }
|
||||
val atx = aliceNode.database.transaction { aliceNode.services.validatedTransactions.getTransaction(stx.id) }
|
||||
val btx = bobNode.database.transaction { bobNode.services.validatedTransactions.getTransaction(stx.id) }
|
||||
requireNotNull(atx)
|
||||
requireNotNull(btx)
|
||||
|
||||
// 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()
|
||||
assertFailsWith(UnexpectedFlowEndException::class) { rejectedFuture.getOrThrow() }
|
||||
|
||||
// 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()
|
||||
b.services.startFlow(ContractUpgradeFlow.Deauthorise(btx.tx.outRef<ContractState>(0).ref)).resultFuture.getOrThrow()
|
||||
bobNode.services.startFlow(ContractUpgradeFlow.Authorise(btx!!.tx.outRef<ContractState>(0), DummyContractV2::class.java)).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.
|
||||
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()
|
||||
assertFailsWith(UnexpectedFlowEndException::class) { deauthorisedFuture.getOrThrow() }
|
||||
|
||||
// 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.
|
||||
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()
|
||||
|
||||
val result = resultFuture.getOrThrow()
|
||||
@ -113,8 +113,8 @@ class ContractUpgradeFlowTest {
|
||||
// Verify outputs.
|
||||
assertTrue(nodeStx!!.tx.outputs.single().data is DummyContractV2.State)
|
||||
}
|
||||
check(a)
|
||||
check(b)
|
||||
check(aliceNode)
|
||||
check(bobNode)
|
||||
}
|
||||
|
||||
private fun RPCDriverExposedDSLInterface.startProxy(node: StartedNode<*>, user: User): CordaRPCOps {
|
||||
@ -132,9 +132,9 @@ class ContractUpgradeFlowTest {
|
||||
fun `2 parties contract upgrade using RPC`() {
|
||||
rpcDriver(initialiseSerialization = false) {
|
||||
// Create dummy contract.
|
||||
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, a.info.chooseIdentity().ref(1), b.info.chooseIdentity().ref(1))
|
||||
val signedByA = a.services.signInitialTransaction(twoPartyDummyContract)
|
||||
val stx = b.services.addSignature(signedByA)
|
||||
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, aliceNode.info.chooseIdentity().ref(1), bobNode.info.chooseIdentity().ref(1))
|
||||
val signedByA = aliceNode.services.signInitialTransaction(twoPartyDummyContract)
|
||||
val stx = bobNode.services.addSignature(signedByA)
|
||||
|
||||
val user = rpcTestUser.copy(permissions = setOf(
|
||||
startFlowPermission<FinalityInvoker>(),
|
||||
@ -142,14 +142,14 @@ class ContractUpgradeFlowTest {
|
||||
startFlowPermission<ContractUpgradeFlow.Authorise>(),
|
||||
startFlowPermission<ContractUpgradeFlow.Deauthorise>()
|
||||
))
|
||||
val rpcA = startProxy(a, user)
|
||||
val rpcB = startProxy(b, user)
|
||||
val handle = rpcA.startFlow(::FinalityInvoker, stx, setOf(b.info.chooseIdentity()))
|
||||
val rpcA = startProxy(aliceNode, user)
|
||||
val rpcB = startProxy(bobNode, user)
|
||||
val handle = rpcA.startFlow(::FinalityInvoker, stx, setOf(bobNode.info.chooseIdentity()))
|
||||
mockNet.runNetwork()
|
||||
handle.returnValue.getOrThrow()
|
||||
|
||||
val atx = a.database.transaction { a.services.validatedTransactions.getTransaction(stx.id) }
|
||||
val btx = b.database.transaction { b.services.validatedTransactions.getTransaction(stx.id) }
|
||||
val atx = aliceNode.database.transaction { aliceNode.services.validatedTransactions.getTransaction(stx.id) }
|
||||
val btx = bobNode.database.transaction { bobNode.services.validatedTransactions.getTransaction(stx.id) }
|
||||
requireNotNull(atx)
|
||||
requireNotNull(btx)
|
||||
|
||||
@ -188,12 +188,12 @@ class ContractUpgradeFlowTest {
|
||||
mockNet.runNetwork()
|
||||
val result = resultFuture.getOrThrow()
|
||||
// Check results.
|
||||
listOf(a, b).forEach {
|
||||
val signedTX = a.database.transaction { a.services.validatedTransactions.getTransaction(result.ref.txhash) }
|
||||
listOf(aliceNode, bobNode).forEach {
|
||||
val signedTX = aliceNode.database.transaction { aliceNode.services.validatedTransactions.getTransaction(result.ref.txhash) }
|
||||
requireNotNull(signedTX)
|
||||
|
||||
// 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)
|
||||
assertTrue(input!!.tx.outputs.single().data is DummyContract.State)
|
||||
|
||||
@ -206,20 +206,20 @@ class ContractUpgradeFlowTest {
|
||||
@Test
|
||||
fun `upgrade Cash to v2`() {
|
||||
// Create some cash.
|
||||
val chosenIdentity = a.info.chooseIdentity()
|
||||
val result = a.services.startFlow(CashIssueFlow(Amount(1000, USD), OpaqueBytes.of(1), notary)).resultFuture
|
||||
val chosenIdentity = aliceNode.info.chooseIdentity()
|
||||
val result = aliceNode.services.startFlow(CashIssueFlow(Amount(1000, USD), OpaqueBytes.of(1), notary)).resultFuture
|
||||
mockNet.runNetwork()
|
||||
val stx = result.getOrThrow().stx
|
||||
val anonymisedRecipient = result.get().recipient!!
|
||||
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.")
|
||||
// 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()
|
||||
upgradeResult.getOrThrow()
|
||||
// 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.")
|
||||
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.")
|
||||
|
@ -7,13 +7,8 @@ import net.corda.finance.POUNDS
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.issuedBy
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.*
|
||||
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.Before
|
||||
import org.junit.Test
|
||||
@ -22,21 +17,20 @@ import kotlin.test.assertFailsWith
|
||||
|
||||
class FinalityFlowTests {
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var nodeA: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var nodeB: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var aliceNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var bobNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var notary: Party
|
||||
val services = MockServices()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
setCordappPackages("net.corda.finance.contracts.asset")
|
||||
mockNet = MockNetwork()
|
||||
val nodes = mockNet.createSomeNodes(2)
|
||||
nodeA = nodes.partyNodes[0]
|
||||
nodeB = nodes.partyNodes[1]
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
mockNet.runNetwork()
|
||||
nodeA.internals.ensureRegistered()
|
||||
notary = nodeA.services.getDefaultNotary()
|
||||
aliceNode.internals.ensureRegistered()
|
||||
notary = aliceNode.services.getDefaultNotary()
|
||||
}
|
||||
|
||||
@After
|
||||
@ -47,28 +41,28 @@ class FinalityFlowTests {
|
||||
|
||||
@Test
|
||||
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)
|
||||
Cash().generateIssue(builder, amount, nodeB.info.chooseIdentity(), notary)
|
||||
val stx = nodeA.services.signInitialTransaction(builder)
|
||||
val flow = nodeA.services.startFlow(FinalityFlow(stx))
|
||||
Cash().generateIssue(builder, amount, bobNode.info.chooseIdentity(), notary)
|
||||
val stx = aliceNode.services.signInitialTransaction(builder)
|
||||
val flow = aliceNode.services.startFlow(FinalityFlow(stx))
|
||||
mockNet.runNetwork()
|
||||
val notarisedTx = flow.resultFuture.getOrThrow()
|
||||
notarisedTx.verifyRequiredSignatures()
|
||||
val transactionSeenByB = nodeB.services.database.transaction {
|
||||
nodeB.services.validatedTransactions.getTransaction(notarisedTx.id)
|
||||
val transactionSeenByB = bobNode.services.database.transaction {
|
||||
bobNode.services.validatedTransactions.getTransaction(notarisedTx.id)
|
||||
}
|
||||
assertEquals(notarisedTx, transactionSeenByB)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `reject a transaction with unknown parties`() {
|
||||
val amount = 1000.POUNDS.issuedBy(nodeA.info.chooseIdentity().ref(0))
|
||||
val fakeIdentity = ALICE // Alice isn't part of this network, so node A won't recognise them
|
||||
val amount = 1000.POUNDS.issuedBy(aliceNode.info.chooseIdentity().ref(0))
|
||||
val fakeIdentity = CHARLIE // Charlie isn't part of this network, so node A won't recognise them
|
||||
val builder = TransactionBuilder(notary)
|
||||
Cash().generateIssue(builder, amount, fakeIdentity, notary)
|
||||
val stx = nodeA.services.signInitialTransaction(builder)
|
||||
val flow = nodeA.services.startFlow(FinalityFlow(stx))
|
||||
val stx = aliceNode.services.signInitialTransaction(builder)
|
||||
val flow = aliceNode.services.startFlow(FinalityFlow(stx))
|
||||
mockNet.runNetwork()
|
||||
assertFailsWith<IllegalArgumentException> {
|
||||
flow.resultFuture.getOrThrow()
|
||||
|
@ -12,7 +12,6 @@ import net.corda.testing.*
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@ -27,25 +26,26 @@ import kotlin.test.assertNull
|
||||
|
||||
class ResolveTransactionsFlowTest {
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var a: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var b: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var notaryNode: 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 megaCorpServices: MockServices
|
||||
lateinit var notaryServices: MockServices
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
setCordappPackages("net.corda.testing.contracts")
|
||||
megaCorpServices = MockServices(MEGA_CORP_KEY)
|
||||
notaryServices = MockServices(DUMMY_NOTARY_KEY)
|
||||
mockNet = MockNetwork()
|
||||
val nodes = mockNet.createSomeNodes()
|
||||
a = nodes.partyNodes[0]
|
||||
b = nodes.partyNodes[1]
|
||||
a.internals.registerInitiatedFlow(TestResponseFlow::class.java)
|
||||
b.internals.registerInitiatedFlow(TestResponseFlow::class.java)
|
||||
notaryNode = mockNet.createNotaryNode()
|
||||
megaCorpNode = mockNet.createPartyNode(notaryNode.network.myAddress, MEGA_CORP.name)
|
||||
miniCorpNode = mockNet.createPartyNode(notaryNode.network.myAddress, MINI_CORP.name)
|
||||
megaCorpNode.internals.registerInitiatedFlow(TestResponseFlow::class.java)
|
||||
miniCorpNode.internals.registerInitiatedFlow(TestResponseFlow::class.java)
|
||||
mockNet.runNetwork()
|
||||
notary = a.services.getDefaultNotary()
|
||||
notary = notaryNode.services.getDefaultNotary()
|
||||
megaCorp = megaCorpNode.info.chooseIdentity()
|
||||
miniCorp = miniCorpNode.info.chooseIdentity()
|
||||
}
|
||||
|
||||
@After
|
||||
@ -58,14 +58,14 @@ class ResolveTransactionsFlowTest {
|
||||
@Test
|
||||
fun `resolve from two hashes`() {
|
||||
val (stx1, stx2) = makeTransactions()
|
||||
val p = TestFlow(setOf(stx2.id), a.info.chooseIdentity())
|
||||
val future = b.services.startFlow(p).resultFuture
|
||||
val p = TestFlow(setOf(stx2.id), megaCorp)
|
||||
val future = miniCorpNode.services.startFlow(p).resultFuture
|
||||
mockNet.runNetwork()
|
||||
val results = future.getOrThrow()
|
||||
assertEquals(listOf(stx1.id, stx2.id), results.map { it.id })
|
||||
b.database.transaction {
|
||||
assertEquals(stx1, b.services.validatedTransactions.getTransaction(stx1.id))
|
||||
assertEquals(stx2, b.services.validatedTransactions.getTransaction(stx2.id))
|
||||
miniCorpNode.database.transaction {
|
||||
assertEquals(stx1, miniCorpNode.services.validatedTransactions.getTransaction(stx1.id))
|
||||
assertEquals(stx2, miniCorpNode.services.validatedTransactions.getTransaction(stx2.id))
|
||||
}
|
||||
}
|
||||
// DOCEND 1
|
||||
@ -73,8 +73,8 @@ class ResolveTransactionsFlowTest {
|
||||
@Test
|
||||
fun `dependency with an error`() {
|
||||
val stx = makeTransactions(signFirstTX = false).second
|
||||
val p = TestFlow(setOf(stx.id), a.info.chooseIdentity())
|
||||
val future = b.services.startFlow(p).resultFuture
|
||||
val p = TestFlow(setOf(stx.id), megaCorp)
|
||||
val future = miniCorpNode.services.startFlow(p).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertFailsWith(SignedTransaction.SignaturesMissingException::class) { future.getOrThrow() }
|
||||
}
|
||||
@ -82,14 +82,14 @@ class ResolveTransactionsFlowTest {
|
||||
@Test
|
||||
fun `resolve from a signed transaction`() {
|
||||
val (stx1, stx2) = makeTransactions()
|
||||
val p = TestFlow(stx2, a.info.chooseIdentity())
|
||||
val future = b.services.startFlow(p).resultFuture
|
||||
val p = TestFlow(stx2, megaCorp)
|
||||
val future = miniCorpNode.services.startFlow(p).resultFuture
|
||||
mockNet.runNetwork()
|
||||
future.getOrThrow()
|
||||
b.database.transaction {
|
||||
assertEquals(stx1, b.services.validatedTransactions.getTransaction(stx1.id))
|
||||
miniCorpNode.database.transaction {
|
||||
assertEquals(stx1, miniCorpNode.services.validatedTransactions.getTransaction(stx1.id))
|
||||
// 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
|
||||
var cursor = stx2
|
||||
repeat(count) {
|
||||
val builder = DummyContract.move(cursor.tx.outRef(0), MINI_CORP)
|
||||
val stx = megaCorpServices.signInitialTransaction(builder)
|
||||
a.database.transaction {
|
||||
a.services.recordTransactions(stx)
|
||||
val builder = DummyContract.move(cursor.tx.outRef(0), miniCorp)
|
||||
val stx = megaCorpNode.services.signInitialTransaction(builder)
|
||||
megaCorpNode.database.transaction {
|
||||
megaCorpNode.services.recordTransactions(stx)
|
||||
}
|
||||
cursor = stx
|
||||
}
|
||||
val p = TestFlow(setOf(cursor.id), a.info.chooseIdentity(), 40)
|
||||
val future = b.services.startFlow(p).resultFuture
|
||||
val p = TestFlow(setOf(cursor.id), megaCorp, 40)
|
||||
val future = miniCorpNode.services.startFlow(p).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertFailsWith<ResolveTransactionsFlow.ExcessivelyLargeTransactionGraph> { future.getOrThrow() }
|
||||
}
|
||||
@ -117,22 +117,22 @@ class ResolveTransactionsFlowTest {
|
||||
fun `triangle of transactions resolves fine`() {
|
||||
val stx1 = makeTransactions().first
|
||||
|
||||
val stx2 = DummyContract.move(stx1.tx.outRef(0), MINI_CORP).run {
|
||||
val ptx = megaCorpServices.signInitialTransaction(this)
|
||||
notaryServices.addSignature(ptx)
|
||||
val stx2 = DummyContract.move(stx1.tx.outRef(0), miniCorp).let { builder ->
|
||||
val ptx = megaCorpNode.services.signInitialTransaction(builder)
|
||||
notaryNode.services.addSignature(ptx, notary.owningKey)
|
||||
}
|
||||
|
||||
val stx3 = DummyContract.move(listOf(stx1.tx.outRef(0), stx2.tx.outRef(0)), MINI_CORP).run {
|
||||
val ptx = megaCorpServices.signInitialTransaction(this)
|
||||
notaryServices.addSignature(ptx)
|
||||
val stx3 = DummyContract.move(listOf(stx1.tx.outRef(0), stx2.tx.outRef(0)), miniCorp).let { builder ->
|
||||
val ptx = megaCorpNode.services.signInitialTransaction(builder)
|
||||
notaryNode.services.addSignature(ptx, notary.owningKey)
|
||||
}
|
||||
|
||||
a.database.transaction {
|
||||
a.services.recordTransactions(stx2, stx3)
|
||||
megaCorpNode.database.transaction {
|
||||
megaCorpNode.services.recordTransactions(stx2, stx3)
|
||||
}
|
||||
|
||||
val p = TestFlow(setOf(stx3.id), a.info.chooseIdentity())
|
||||
val future = b.services.startFlow(p).resultFuture
|
||||
val p = TestFlow(setOf(stx3.id), megaCorp)
|
||||
val future = miniCorpNode.services.startFlow(p).resultFuture
|
||||
mockNet.runNetwork()
|
||||
future.getOrThrow()
|
||||
}
|
||||
@ -149,43 +149,43 @@ class ResolveTransactionsFlowTest {
|
||||
return bs.toByteArray().sequence().open()
|
||||
}
|
||||
// TODO: this operation should not require an explicit transaction
|
||||
val id = a.database.transaction {
|
||||
a.services.attachments.importAttachment(makeJar())
|
||||
val id = megaCorpNode.database.transaction {
|
||||
megaCorpNode.services.attachments.importAttachment(makeJar())
|
||||
}
|
||||
val stx2 = makeTransactions(withAttachment = id).second
|
||||
val p = TestFlow(stx2, a.info.chooseIdentity())
|
||||
val future = b.services.startFlow(p).resultFuture
|
||||
val p = TestFlow(stx2, megaCorp)
|
||||
val future = miniCorpNode.services.startFlow(p).resultFuture
|
||||
mockNet.runNetwork()
|
||||
future.getOrThrow()
|
||||
|
||||
// TODO: this operation should not require an explicit transaction
|
||||
b.database.transaction {
|
||||
assertNotNull(b.services.attachments.openAttachment(id))
|
||||
miniCorpNode.database.transaction {
|
||||
assertNotNull(miniCorpNode.services.attachments.openAttachment(id))
|
||||
}
|
||||
}
|
||||
|
||||
// DOCSTART 2
|
||||
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.
|
||||
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)
|
||||
it.addAttachment(withAttachment)
|
||||
when (signFirstTX) {
|
||||
true -> {
|
||||
val ptx = megaCorpServices.signInitialTransaction(it)
|
||||
notaryServices.addSignature(ptx)
|
||||
val ptx = megaCorpNode.services.signInitialTransaction(it)
|
||||
notaryNode.services.addSignature(ptx, notary.owningKey)
|
||||
}
|
||||
false -> {
|
||||
notaryServices.signInitialTransaction(it)
|
||||
notaryNode.services.signInitialTransaction(it, notary.owningKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
val dummy2: SignedTransaction = DummyContract.move(dummy1.tx.outRef(0), MINI_CORP).let {
|
||||
val ptx = megaCorpServices.signInitialTransaction(it)
|
||||
notaryServices.addSignature(ptx)
|
||||
val dummy2: SignedTransaction = DummyContract.move(dummy1.tx.outRef(0), miniCorp).let {
|
||||
val ptx = megaCorpNode.services.signInitialTransaction(it)
|
||||
notaryNode.services.addSignature(ptx, notary.owningKey)
|
||||
}
|
||||
a.database.transaction {
|
||||
a.services.recordTransactions(dummy1, dummy2)
|
||||
megaCorpNode.database.transaction {
|
||||
megaCorpNode.services.recordTransactions(dummy1, dummy2)
|
||||
}
|
||||
return Pair(dummy1, dummy2)
|
||||
}
|
||||
|
@ -7,13 +7,10 @@ import net.corda.finance.DOLLARS
|
||||
import net.corda.finance.`issued by`
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetwork.MockNode
|
||||
import net.corda.testing.setCordappPackages
|
||||
import net.corda.testing.unsetCordappPackages
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@ -33,9 +30,9 @@ class CashExitFlowTests {
|
||||
fun start() {
|
||||
setCordappPackages("net.corda.finance.contracts.asset")
|
||||
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin())
|
||||
val nodes = mockNet.createSomeNodes(1)
|
||||
notaryNode = nodes.notaryNode
|
||||
bankOfCordaNode = nodes.partyNodes[0]
|
||||
notaryNode = mockNet.createNotaryNode()
|
||||
bankOfCordaNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
|
||||
notary = notaryNode.services.getDefaultNotary()
|
||||
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
|
||||
|
||||
mockNet.runNetwork()
|
||||
|
@ -9,6 +9,8 @@ import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.chooseIdentity
|
||||
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.MockNetwork
|
||||
import net.corda.testing.node.MockNetwork.MockNode
|
||||
@ -30,13 +32,11 @@ class CashIssueFlowTests {
|
||||
fun start() {
|
||||
setCordappPackages("net.corda.finance.contracts.asset")
|
||||
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin())
|
||||
val nodes = mockNet.createSomeNodes(1)
|
||||
notaryNode = nodes.notaryNode
|
||||
bankOfCordaNode = nodes.partyNodes[0]
|
||||
notaryNode = mockNet.createNotaryNode()
|
||||
bankOfCordaNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
|
||||
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
|
||||
|
||||
notary = notaryNode.services.getDefaultNotary()
|
||||
mockNet.runNetwork()
|
||||
notary = bankOfCordaNode.services.getDefaultNotary()
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -33,9 +33,8 @@ class CashPaymentFlowTests {
|
||||
fun start() {
|
||||
setCordappPackages("net.corda.finance.contracts.asset")
|
||||
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin())
|
||||
val nodes = mockNet.createSomeNodes(1)
|
||||
notaryNode = nodes.notaryNode
|
||||
bankOfCordaNode = nodes.partyNodes[0]
|
||||
notaryNode = mockNet.createNotaryNode()
|
||||
bankOfCordaNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
|
||||
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
|
||||
notary = notaryNode.services.getDefaultNotary()
|
||||
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture
|
||||
|
@ -93,15 +93,13 @@ class TwoPartyTradeFlowTests {
|
||||
mockNet = MockNetwork(false, true)
|
||||
|
||||
ledger(initialiseSerialization = false) {
|
||||
val basketOfNodes = mockNet.createSomeNodes(3)
|
||||
val notaryNode = basketOfNodes.notaryNode
|
||||
val aliceNode = basketOfNodes.partyNodes[0]
|
||||
val bobNode = basketOfNodes.partyNodes[1]
|
||||
val bankNode = basketOfNodes.partyNodes[2]
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
|
||||
val notary = notaryNode.services.getDefaultNotary()
|
||||
val cashIssuer = bankNode.info.chooseIdentity().ref(1)
|
||||
val cpIssuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
|
||||
val notary = aliceNode.services.getDefaultNotary()
|
||||
|
||||
|
||||
aliceNode.internals.disableDBCloseOnStop()
|
||||
bobNode.internals.disableDBCloseOnStop()
|
||||
@ -144,7 +142,7 @@ class TwoPartyTradeFlowTests {
|
||||
mockNet = MockNetwork(false, true)
|
||||
|
||||
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 bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
|
||||
@ -198,7 +196,7 @@ class TwoPartyTradeFlowTests {
|
||||
fun `shutdown and restore`() {
|
||||
mockNet = MockNetwork(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)
|
||||
var bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
|
||||
@ -332,7 +330,7 @@ class TwoPartyTradeFlowTests {
|
||||
fun `check dependencies of sale asset are resolved`() {
|
||||
mockNet = MockNetwork(false)
|
||||
|
||||
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
|
||||
val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
|
||||
val bankNode = makeNodeWithTracking(notaryNode.network.myAddress, BOC.name)
|
||||
@ -439,7 +437,7 @@ class TwoPartyTradeFlowTests {
|
||||
fun `track works`() {
|
||||
mockNet = MockNetwork(false)
|
||||
|
||||
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
|
||||
val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
|
||||
val bankNode = makeNodeWithTracking(notaryNode.network.myAddress, BOC.name)
|
||||
@ -596,7 +594,7 @@ class TwoPartyTradeFlowTests {
|
||||
aliceError: Boolean,
|
||||
expectedMessageSubstring: String
|
||||
) {
|
||||
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
|
||||
|
@ -5,6 +5,7 @@ import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.nodeapi.internal.ServiceInfo
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
@ -29,10 +30,9 @@ class NetworkMapCacheTest {
|
||||
|
||||
@Test
|
||||
fun registerWithNetwork() {
|
||||
val nodes = mockNet.createSomeNodes(1)
|
||||
val n0 = nodes.mapNode
|
||||
val n1 = nodes.partyNodes[0]
|
||||
val future = n1.services.networkMapCache.addMapService(n1.network, n0.network.myAddress, false, null)
|
||||
val mapNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(mapNode.network.myAddress, ALICE.name)
|
||||
val future = aliceNode.services.networkMapCache.addMapService(aliceNode.network, mapNode.network.myAddress, false, null)
|
||||
mockNet.runNetwork()
|
||||
future.getOrThrow()
|
||||
}
|
||||
@ -40,30 +40,29 @@ class NetworkMapCacheTest {
|
||||
@Test
|
||||
fun `key collision`() {
|
||||
val entropy = BigInteger.valueOf(24012017L)
|
||||
val nodeA = 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))
|
||||
assertEquals(nodeA.info.chooseIdentity(), nodeB.info.chooseIdentity())
|
||||
val aliceNode = mockNet.createNode(nodeFactory = MockNetwork.DefaultFactory, legalName = ALICE.name, entropyRoot = entropy, advertisedServices = ServiceInfo(NetworkMapService.type))
|
||||
val bobNode = mockNet.createNode(nodeFactory = MockNetwork.DefaultFactory, legalName = BOB.name, entropyRoot = entropy, advertisedServices = ServiceInfo(NetworkMapService.type))
|
||||
assertEquals(aliceNode.info.chooseIdentity(), bobNode.info.chooseIdentity())
|
||||
|
||||
mockNet.runNetwork()
|
||||
|
||||
// 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
|
||||
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
|
||||
fun `getNodeByLegalIdentity`() {
|
||||
val nodes = mockNet.createSomeNodes(1)
|
||||
val n0 = nodes.mapNode
|
||||
val n1 = nodes.partyNodes[0]
|
||||
val node0Cache: NetworkMapCache = n0.services.networkMapCache
|
||||
val expected = n1.info
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
val notaryCache: NetworkMapCache = notaryNode.services.networkMapCache
|
||||
val expected = aliceNode.info
|
||||
|
||||
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)
|
||||
|
||||
// TODO: Should have a test case with anonymous lookup
|
||||
@ -71,19 +70,18 @@ class NetworkMapCacheTest {
|
||||
|
||||
@Test
|
||||
fun `remove node from cache`() {
|
||||
val nodes = mockNet.createSomeNodes(1)
|
||||
val n0 = nodes.mapNode
|
||||
val n1 = nodes.partyNodes[0]
|
||||
val n0Identity = n0.info.chooseIdentity()
|
||||
val n1Identity = n1.info.chooseIdentity()
|
||||
val node0Cache = n0.services.networkMapCache as PersistentNetworkMapCache
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
val notaryLegalIdentity = notaryNode.info.chooseIdentity()
|
||||
val alice = aliceNode.info.chooseIdentity()
|
||||
val notaryCache = notaryNode.services.networkMapCache as PersistentNetworkMapCache
|
||||
mockNet.runNetwork()
|
||||
n0.database.transaction {
|
||||
assertThat(node0Cache.getNodeByLegalIdentity(n1Identity) != null)
|
||||
node0Cache.removeNode(n1.info)
|
||||
assertThat(node0Cache.getNodeByLegalIdentity(n1Identity) == null)
|
||||
assertThat(node0Cache.getNodeByLegalIdentity(n0Identity) != null)
|
||||
assertThat(node0Cache.getNodeByLegalName(n1Identity.name) == null)
|
||||
notaryNode.database.transaction {
|
||||
assertThat(notaryCache.getNodeByLegalIdentity(alice) != null)
|
||||
notaryCache.removeNode(aliceNode.info)
|
||||
assertThat(notaryCache.getNodeByLegalIdentity(alice) == null)
|
||||
assertThat(notaryCache.getNodeByLegalIdentity(notaryLegalIdentity) != null)
|
||||
assertThat(notaryCache.getNodeByLegalName(alice.name) == null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
* clearly separated, but this is convenient for testing.
|
||||
* Construct a default notary node.
|
||||
*/
|
||||
data class BasketOfNodes(val partyNodes: List<StartedNode<MockNode>>, val notaryNode: StartedNode<MockNode>, val mapNode: StartedNode<MockNode>)
|
||||
|
||||
/**
|
||||
* 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() = createNotaryNode(null, DUMMY_NOTARY.name, null, null)
|
||||
|
||||
fun createNotaryNode(networkMapAddress: SingleMessageRecipient? = null,
|
||||
legalName: CordaX500Name? = null,
|
||||
@ -413,6 +391,10 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
||||
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,
|
||||
legalName: CordaX500Name? = null,
|
||||
overrideServices: Map<ServiceInfo, KeyPair>? = null): StartedNode<MockNode> {
|
||||
|
Loading…
Reference in New Issue
Block a user