mirror of
https://github.com/corda/corda.git
synced 2024-12-20 05:28:21 +00:00
Removed the ability to manually start notary nodes from the driver and MockNetwork. Instead by default a single notary is automatically started. This can be customised at creation time of the driver and MockNetwork. This more accurately models the concept of network parameters in a CZ.
Also added helper methods to retrieve this default notary.
This commit is contained in:
parent
9be37c2b88
commit
3bb018a5ce
@ -11,7 +11,6 @@ import net.corda.core.flows.StateMachineRunId
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.bufferUntilSubscribed
|
||||
import net.corda.core.internal.concurrent.transpose
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.messaging.StateMachineTransactionMapping
|
||||
import net.corda.core.messaging.StateMachineUpdate
|
||||
@ -50,7 +49,9 @@ class NodeMonitorModelTest {
|
||||
private lateinit var vaultUpdates: Observable<Vault.Update<ContractState>>
|
||||
private lateinit var networkMapUpdates: Observable<NetworkMapCache.MapChange>
|
||||
private lateinit var newNode: (CordaX500Name) -> NodeInfo
|
||||
private fun setup(runTest: () -> Unit) = driver(extraCordappPackagesToScan = listOf("net.corda.finance")) {
|
||||
|
||||
private fun setup(runTest: () -> Unit) {
|
||||
driver(extraCordappPackagesToScan = listOf("net.corda.finance")) {
|
||||
val cashUser = User("user1", "test", permissions = setOf(
|
||||
startFlow<CashIssueFlow>(),
|
||||
startFlow<CashPaymentFlow>(),
|
||||
@ -63,10 +64,7 @@ class NodeMonitorModelTest {
|
||||
invokeRpc(CordaRPCOps::stateMachinesFeed),
|
||||
invokeRpc(CordaRPCOps::networkMapFeed))
|
||||
)
|
||||
val (notaryHandle, aliceNodeHandle) = listOf(
|
||||
startNotaryNode(DUMMY_NOTARY.name, validating = false),
|
||||
startNode(providedName = ALICE.name, rpcUsers = listOf(cashUser))
|
||||
).transpose().getOrThrow()
|
||||
val aliceNodeHandle = startNode(providedName = ALICE.name, rpcUsers = listOf(cashUser)).getOrThrow()
|
||||
aliceNode = aliceNodeHandle.nodeInfo
|
||||
newNode = { nodeName -> startNode(providedName = nodeName).getOrThrow().nodeInfo }
|
||||
val monitor = NodeMonitorModel()
|
||||
@ -79,7 +77,7 @@ class NodeMonitorModelTest {
|
||||
|
||||
monitor.register(aliceNodeHandle.configuration.rpcAddress!!, cashUser.username, cashUser.password)
|
||||
rpc = monitor.proxyObservable.value!!
|
||||
notaryParty = notaryHandle.nodeInfo.legalIdentities[0]
|
||||
notaryParty = defaultNotaryIdentity
|
||||
|
||||
val bobNodeHandle = startNode(providedName = BOB.name, rpcUsers = listOf(cashUser)).getOrThrow()
|
||||
bobNode = bobNodeHandle.nodeInfo
|
||||
@ -89,6 +87,7 @@ class NodeMonitorModelTest {
|
||||
rpcBob = monitorBob.proxyObservable.value!!
|
||||
runTest()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `network map update`() = setup {
|
||||
|
@ -14,8 +14,11 @@ import net.corda.finance.DOLLARS
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
||||
import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.ALICE_NAME
|
||||
import net.corda.testing.BOB_NAME
|
||||
import net.corda.testing.CHARLIE_NAME
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.singleIdentity
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@ -24,12 +27,16 @@ import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
|
||||
class IdentitySyncFlowTests {
|
||||
lateinit var mockNet: MockNetwork
|
||||
private lateinit var mockNet: MockNetwork
|
||||
|
||||
@Before
|
||||
fun before() {
|
||||
// We run this in parallel threads to help catch any race conditions that may exist.
|
||||
mockNet = MockNetwork(networkSendManuallyPumped = false, threadPerNode = true, cordappPackages = listOf("net.corda.finance.contracts.asset"))
|
||||
mockNet = MockNetwork(
|
||||
networkSendManuallyPumped = false,
|
||||
threadPerNode = true,
|
||||
cordappPackages = listOf("net.corda.finance.contracts.asset")
|
||||
)
|
||||
}
|
||||
|
||||
@After
|
||||
@ -40,12 +47,11 @@ class IdentitySyncFlowTests {
|
||||
@Test
|
||||
fun `sync confidential identities`() {
|
||||
// Set up values we'll need
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
||||
val bobNode = mockNet.createPartyNode(BOB_NAME)
|
||||
val alice: Party = aliceNode.info.singleIdentity()
|
||||
val bob: Party = bobNode.info.singleIdentity()
|
||||
val notary = notaryNode.services.getDefaultNotary()
|
||||
val notary = mockNet.defaultNotaryIdentity
|
||||
bobNode.internals.registerInitiatedFlow(Receive::class.java)
|
||||
|
||||
// Alice issues then pays some cash to a new confidential identity that Bob doesn't know about
|
||||
@ -70,14 +76,13 @@ class IdentitySyncFlowTests {
|
||||
@Test
|
||||
fun `don't offer other's identities confidential identities`() {
|
||||
// Set up values we'll need
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
||||
val bobNode = mockNet.createPartyNode(BOB_NAME)
|
||||
val charlieNode = mockNet.createPartyNode(CHARLIE_NAME)
|
||||
val alice: Party = aliceNode.info.singleIdentity()
|
||||
val bob: Party = bobNode.info.singleIdentity()
|
||||
val charlie: Party = charlieNode.info.singleIdentity()
|
||||
val notary = notaryNode.services.getDefaultNotary()
|
||||
val notary = mockNet.defaultNotaryIdentity
|
||||
bobNode.internals.registerInitiatedFlow(Receive::class.java)
|
||||
|
||||
// Charlie issues then pays some cash to a new confidential identity
|
||||
@ -105,7 +110,7 @@ class IdentitySyncFlowTests {
|
||||
* Very lightweight wrapping flow to trigger the counterparty flow that receives the identities.
|
||||
*/
|
||||
@InitiatingFlow
|
||||
class Initiator(val otherSide: Party, val tx: WireTransaction): FlowLogic<Boolean>() {
|
||||
class Initiator(private val otherSide: Party, private val tx: WireTransaction): FlowLogic<Boolean>() {
|
||||
@Suspendable
|
||||
override fun call(): Boolean {
|
||||
val session = initiateFlow(otherSide)
|
||||
@ -116,7 +121,7 @@ class IdentitySyncFlowTests {
|
||||
}
|
||||
|
||||
@InitiatedBy(IdentitySyncFlowTests.Initiator::class)
|
||||
class Receive(val otherSideSession: FlowSession): FlowLogic<Unit>() {
|
||||
class Receive(private val otherSideSession: FlowSession): FlowLogic<Unit>() {
|
||||
@Suspendable
|
||||
override fun call() {
|
||||
subFlow(IdentitySyncFlow.Receive(otherSideSession))
|
||||
|
@ -6,17 +6,22 @@ import net.corda.core.identity.Party
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import kotlin.test.*
|
||||
|
||||
class SwapIdentitiesFlowTests {
|
||||
private lateinit var mockNet: MockNetwork
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
// We run this in parallel threads to help catch any race conditions that may exist.
|
||||
mockNet = MockNetwork(networkSendManuallyPumped = false, threadPerNode = true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `issue key`() {
|
||||
// We run this in parallel threads to help catch any race conditions that may exist.
|
||||
val mockNet = MockNetwork(threadPerNode = true)
|
||||
|
||||
// Set up values we'll need
|
||||
mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(ALICE.name)
|
||||
val bobNode = mockNet.createPartyNode(BOB.name)
|
||||
val alice = aliceNode.info.singleIdentity()
|
||||
@ -52,19 +57,16 @@ class SwapIdentitiesFlowTests {
|
||||
*/
|
||||
@Test
|
||||
fun `verifies identity name`() {
|
||||
// We run this in parallel threads to help catch any race conditions that may exist.
|
||||
val mockNet = MockNetwork(threadPerNode = true)
|
||||
|
||||
// Set up values we'll need
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(ALICE.name)
|
||||
val bobNode = mockNet.createPartyNode(BOB.name)
|
||||
val charlieNode = mockNet.createPartyNode(CHARLIE.name)
|
||||
val bob: Party = bobNode.services.myInfo.singleIdentity()
|
||||
val notBob = notaryNode.database.transaction {
|
||||
notaryNode.services.keyManagementService.freshKeyAndCert(notaryNode.services.myInfo.chooseIdentityAndCert(), false)
|
||||
val notBob = charlieNode.database.transaction {
|
||||
charlieNode.services.keyManagementService.freshKeyAndCert(charlieNode.services.myInfo.chooseIdentityAndCert(), false)
|
||||
}
|
||||
val sigData = SwapIdentitiesFlow.buildDataToSign(notBob)
|
||||
val signature = notaryNode.services.keyManagementService.sign(sigData, notBob.owningKey)
|
||||
val signature = charlieNode.services.keyManagementService.sign(sigData, notBob.owningKey)
|
||||
assertFailsWith<SwapIdentitiesException>("Certificate subject must match counterparty's well known identity.") {
|
||||
SwapIdentitiesFlow.validateAndRegisterIdentity(aliceNode.services.identityService, bob, notBob, signature.withoutKey())
|
||||
}
|
||||
@ -77,11 +79,8 @@ class SwapIdentitiesFlowTests {
|
||||
*/
|
||||
@Test
|
||||
fun `verifies signature`() {
|
||||
// We run this in parallel threads to help catch any race conditions that may exist.
|
||||
val mockNet = MockNetwork(threadPerNode = true)
|
||||
|
||||
// Set up values we'll need
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val notaryNode = mockNet.defaultNotaryNode
|
||||
val aliceNode = mockNet.createPartyNode(ALICE.name)
|
||||
val bobNode = mockNet.createPartyNode(BOB.name)
|
||||
val bob: Party = bobNode.services.myInfo.singleIdentity()
|
||||
|
@ -120,7 +120,7 @@ interface NetworkMapCacheBase {
|
||||
|
||||
/**
|
||||
* Returns true if and only if the given [Party] is validating notary. For every party that is a validating notary,
|
||||
* [isNotary] is only true.
|
||||
* [isNotary] is also true.
|
||||
* @see isNotary
|
||||
*/
|
||||
fun isValidatingNotary(party: Party): Boolean
|
||||
|
@ -18,14 +18,12 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class FlowsInJavaTest {
|
||||
|
||||
private final MockNetwork mockNet = new MockNetwork();
|
||||
private StartedNode<MockNetwork.MockNode> aliceNode;
|
||||
private StartedNode<MockNetwork.MockNode> bobNode;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mockNet.createNotaryNode();
|
||||
aliceNode = mockNet.createPartyNode(TestConstants.getALICE().getName());
|
||||
bobNode = mockNet.createPartyNode(TestConstants.getBOB().getName());
|
||||
mockNet.runNetwork();
|
||||
|
@ -110,11 +110,11 @@ class AttachmentTests {
|
||||
@Test
|
||||
fun maliciousResponse() {
|
||||
// Make a node that doesn't do sanity checking at load time.
|
||||
val aliceNode = mockNet.createNotaryNode(MockNodeParameters(legalName = ALICE.name), nodeFactory = { args ->
|
||||
val aliceNode = mockNet.createNode(MockNodeParameters(legalName = ALICE.name), nodeFactory = { args ->
|
||||
object : MockNetwork.MockNode(args) {
|
||||
override fun start() = super.start().apply { attachments.checkAttachmentsOnLoad = false }
|
||||
}
|
||||
}, validating = false)
|
||||
})
|
||||
val bobNode = mockNet.createNode(MockNodeParameters(legalName = BOB.name))
|
||||
mockNet.runNetwork()
|
||||
val alice = aliceNode.services.myInfo.identityFromX500Name(ALICE_NAME)
|
||||
|
@ -27,19 +27,18 @@ class CollectSignaturesFlowTests {
|
||||
private val cordappPackages = listOf("net.corda.testing.contracts")
|
||||
}
|
||||
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var aliceNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var bobNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var charlieNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var alice: Party
|
||||
lateinit var bob: Party
|
||||
lateinit var charlie: Party
|
||||
lateinit var notary: Party
|
||||
private lateinit var mockNet: MockNetwork
|
||||
private lateinit var aliceNode: StartedNode<MockNetwork.MockNode>
|
||||
private lateinit var bobNode: StartedNode<MockNetwork.MockNode>
|
||||
private lateinit var charlieNode: StartedNode<MockNetwork.MockNode>
|
||||
private lateinit var alice: Party
|
||||
private lateinit var bob: Party
|
||||
private lateinit var charlie: Party
|
||||
private lateinit var notary: Party
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = MockNetwork(cordappPackages = cordappPackages)
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
aliceNode = mockNet.createPartyNode(ALICE.name)
|
||||
bobNode = mockNet.createPartyNode(BOB.name)
|
||||
charlieNode = mockNet.createPartyNode(CHARLIE.name)
|
||||
@ -47,7 +46,7 @@ class CollectSignaturesFlowTests {
|
||||
alice = aliceNode.info.singleIdentity()
|
||||
bob = bobNode.info.singleIdentity()
|
||||
charlie = charlieNode.info.singleIdentity()
|
||||
notary = notaryNode.services.getDefaultNotary()
|
||||
notary = mockNet.defaultNotaryIdentity
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -41,14 +41,13 @@ class ContractUpgradeFlowTest {
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts", "net.corda.finance.contracts.asset", "net.corda.core.flows"))
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
aliceNode = mockNet.createPartyNode(ALICE.name)
|
||||
bobNode = mockNet.createPartyNode(BOB.name)
|
||||
|
||||
// Process registration
|
||||
mockNet.runNetwork()
|
||||
|
||||
notary = notaryNode.services.getDefaultNotary()
|
||||
notary = mockNet.defaultNotaryIdentity
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -26,7 +26,6 @@ class FinalityFlowTests {
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = MockNetwork(cordappPackages = listOf("net.corda.finance.contracts.asset"))
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
||||
val bobNode = mockNet.createPartyNode(BOB_NAME)
|
||||
mockNet.runNetwork()
|
||||
@ -34,7 +33,7 @@ class FinalityFlowTests {
|
||||
bobServices = bobNode.services
|
||||
alice = aliceNode.info.singleIdentity()
|
||||
bob = bobNode.info.singleIdentity()
|
||||
notary = notaryNode.services.getDefaultNotary()
|
||||
notary = aliceServices.getDefaultNotary()
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -13,7 +13,7 @@ import org.junit.Test
|
||||
class ReceiveMultipleFlowTests {
|
||||
@Test
|
||||
fun `receive all messages in parallel using map style`() {
|
||||
network(3) { nodes, _ ->
|
||||
network(3) { nodes ->
|
||||
val doubleValue = 5.0
|
||||
nodes[1].registerAnswer(AlgorithmDefinition::class, doubleValue)
|
||||
val stringValue = "Thriller"
|
||||
@ -30,7 +30,7 @@ class ReceiveMultipleFlowTests {
|
||||
|
||||
@Test
|
||||
fun `receive all messages in parallel using list style`() {
|
||||
network(3) { nodes, _ ->
|
||||
network(3) { nodes ->
|
||||
val value1 = 5.0
|
||||
nodes[1].registerAnswer(ParallelAlgorithmList::class, value1)
|
||||
val value2 = 6.0
|
||||
|
@ -8,7 +8,9 @@ import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.sequence
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.MEGA_CORP
|
||||
import net.corda.testing.MINI_CORP
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
@ -26,18 +28,18 @@ import kotlin.test.assertNull
|
||||
|
||||
// DOCSTART 3
|
||||
class ResolveTransactionsFlowTest {
|
||||
lateinit var mockNet: MockNetwork
|
||||
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
|
||||
private lateinit var mockNet: MockNetwork
|
||||
private lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
|
||||
private lateinit var megaCorpNode: StartedNode<MockNetwork.MockNode>
|
||||
private lateinit var miniCorpNode: StartedNode<MockNetwork.MockNode>
|
||||
private lateinit var megaCorp: Party
|
||||
private lateinit var miniCorp: Party
|
||||
private lateinit var notary: Party
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
|
||||
notaryNode = mockNet.createNotaryNode()
|
||||
notaryNode = mockNet.defaultNotaryNode
|
||||
megaCorpNode = mockNet.createPartyNode(MEGA_CORP.name)
|
||||
miniCorpNode = mockNet.createPartyNode(MINI_CORP.name)
|
||||
megaCorpNode.internals.registerInitiatedFlow(TestResponseFlow::class.java)
|
||||
|
@ -37,8 +37,7 @@ class IntegrationTestingTutorial {
|
||||
invokeRpc("vaultTrackBy"),
|
||||
invokeRpc(CordaRPCOps::networkMapFeed)
|
||||
))
|
||||
val (_, alice, bob) = listOf(
|
||||
startNotaryNode(DUMMY_NOTARY.name),
|
||||
val (alice, bob) = listOf(
|
||||
startNode(providedName = ALICE.name, rpcUsers = listOf(aliceUser)),
|
||||
startNode(providedName = BOB.name, rpcUsers = listOf(bobUser))
|
||||
).transpose().getOrThrow()
|
||||
|
@ -1,3 +1,5 @@
|
||||
@file:Suppress("unused")
|
||||
|
||||
package net.corda.docs
|
||||
|
||||
import net.corda.core.contracts.Amount
|
||||
@ -17,7 +19,6 @@ import net.corda.node.services.Permissions.Companion.invokeRpc
|
||||
import net.corda.node.services.Permissions.Companion.startFlow
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.driver.driver
|
||||
import org.graphstream.graph.Edge
|
||||
import org.graphstream.graph.Node
|
||||
@ -48,7 +49,6 @@ fun main(args: Array<String>) {
|
||||
invokeRpc(CordaRPCOps::nodeInfo)
|
||||
))
|
||||
driver(driverDirectory = baseDirectory, extraCordappPackagesToScan = listOf("net.corda.finance")) {
|
||||
startNotaryNode(DUMMY_NOTARY.name)
|
||||
val node = startNode(providedName = ALICE.name, rpcUsers = listOf(user)).get()
|
||||
// END 1
|
||||
|
||||
|
@ -55,7 +55,6 @@ class TutorialMockNetwork {
|
||||
}
|
||||
|
||||
lateinit private var mockNet: MockNetwork
|
||||
lateinit private var notary: StartedNode<MockNetwork.MockNode>
|
||||
lateinit private var nodeA: StartedNode<MockNetwork.MockNode>
|
||||
lateinit private var nodeB: StartedNode<MockNetwork.MockNode>
|
||||
|
||||
@ -66,7 +65,6 @@ class TutorialMockNetwork {
|
||||
@Before
|
||||
fun setUp() {
|
||||
mockNet = MockNetwork()
|
||||
notary = mockNet.createNotaryNode()
|
||||
nodeA = mockNet.createPartyNode()
|
||||
nodeB = mockNet.createPartyNode()
|
||||
|
||||
|
@ -10,7 +10,8 @@ import net.corda.finance.contracts.getCashBalances
|
||||
import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.finance.schemas.CashSchemaV1
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Assert
|
||||
@ -19,23 +20,20 @@ import org.junit.Test
|
||||
import java.util.*
|
||||
|
||||
class CustomVaultQueryTest {
|
||||
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var nodeA: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var nodeB: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var notary: Party
|
||||
private lateinit var mockNet: MockNetwork
|
||||
private lateinit var nodeA: StartedNode<MockNetwork.MockNode>
|
||||
private lateinit var nodeB: StartedNode<MockNetwork.MockNode>
|
||||
private lateinit var notary: Party
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = MockNetwork(
|
||||
threadPerNode = true,
|
||||
mockNet = MockNetwork(threadPerNode = true,
|
||||
cordappPackages = listOf(
|
||||
"net.corda.finance.contracts.asset",
|
||||
CashSchemaV1::class.packageName,
|
||||
"net.corda.docs"
|
||||
)
|
||||
)
|
||||
mockNet.createNotaryNode()
|
||||
nodeA = mockNet.createPartyNode()
|
||||
nodeB = mockNet.createPartyNode()
|
||||
nodeA.internals.registerInitiatedFlow(TopupIssuerFlow.TopupIssuer::class.java)
|
||||
|
@ -10,7 +10,8 @@ import net.corda.finance.contracts.getCashBalances
|
||||
import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.finance.schemas.CashSchemaV1
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@ -18,15 +19,14 @@ import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class FxTransactionBuildTutorialTest {
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var nodeA: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var nodeB: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var notary: Party
|
||||
private lateinit var mockNet: MockNetwork
|
||||
private lateinit var nodeA: StartedNode<MockNetwork.MockNode>
|
||||
private lateinit var nodeB: StartedNode<MockNetwork.MockNode>
|
||||
private lateinit var notary: Party
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.finance.contracts.asset", CashSchemaV1::class.packageName))
|
||||
mockNet.createNotaryNode()
|
||||
nodeA = mockNet.createPartyNode()
|
||||
nodeB = mockNet.createPartyNode()
|
||||
nodeB.internals.registerInitiatedFlow(ForeignExchangeRemoteFlow::class.java)
|
||||
|
@ -10,7 +10,8 @@ import net.corda.core.node.services.vault.QueryCriteria
|
||||
import net.corda.core.toFuture
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.services.api.StartedNodeServices
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.ALICE_NAME
|
||||
import net.corda.testing.BOB_NAME
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@ -18,11 +19,11 @@ import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class WorkflowTransactionBuildTutorialTest {
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var aliceServices: StartedNodeServices
|
||||
lateinit var bobServices: StartedNodeServices
|
||||
lateinit var alice: Party
|
||||
lateinit var bob: Party
|
||||
private lateinit var mockNet: MockNetwork
|
||||
private lateinit var aliceServices: StartedNodeServices
|
||||
private lateinit var bobServices: StartedNodeServices
|
||||
private lateinit var alice: Party
|
||||
private lateinit var bob: Party
|
||||
|
||||
// Helper method to locate the latest Vault version of a LinearState
|
||||
private inline fun <reified T : LinearState> ServiceHub.latest(ref: UniqueIdentifier): StateAndRef<T> {
|
||||
@ -33,8 +34,6 @@ class WorkflowTransactionBuildTutorialTest {
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.docs"))
|
||||
// While we don't use the notary, we need there to be one on the network
|
||||
mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
||||
val bobNode = mockNet.createPartyNode(BOB_NAME)
|
||||
aliceNode.internals.registerInitiatedFlow(RecordCompletionFlow::class.java)
|
||||
|
@ -1,41 +1,38 @@
|
||||
package net.corda.finance.contracts.asset
|
||||
|
||||
import net.corda.core.internal.packageName
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.finance.DOLLARS
|
||||
import net.corda.finance.flows.CashException
|
||||
import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.finance.schemas.CashSchemaV1
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNodeParameters
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.After
|
||||
import org.junit.Test
|
||||
|
||||
|
||||
class CashSelectionH2Test {
|
||||
private val mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.finance"))
|
||||
|
||||
@After
|
||||
fun cleanUp() {
|
||||
mockNet.stopNodes()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `check does not hold connection over retries`() {
|
||||
val mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.finance.contracts.asset", CashSchemaV1::class.packageName))
|
||||
try {
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val bankA = mockNet.createNode(MockNodeParameters(configOverrides = { existingConfig ->
|
||||
val bankA = mockNet.createNode(MockNodeParameters(configOverrides = {
|
||||
// Tweak connections to be minimal to make this easier (1 results in a hung node during start up, so use 2 connections).
|
||||
existingConfig.dataSourceProperties.setProperty("maximumPoolSize", "2")
|
||||
it.dataSourceProperties.setProperty("maximumPoolSize", "2")
|
||||
}))
|
||||
mockNet.startNodes()
|
||||
val notary = mockNet.defaultNotaryIdentity
|
||||
|
||||
// Start more cash spends than we have connections. If spend leaks a connection on retry, we will run out of connections.
|
||||
val flow1 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notaryNode.info.chooseIdentity()))
|
||||
val flow2 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notaryNode.info.chooseIdentity()))
|
||||
val flow3 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notaryNode.info.chooseIdentity()))
|
||||
val flow1 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notary))
|
||||
val flow2 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notary))
|
||||
val flow3 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notary))
|
||||
|
||||
assertThatThrownBy { flow1.resultFuture.getOrThrow() }.isInstanceOf(CashException::class.java)
|
||||
assertThatThrownBy { flow2.resultFuture.getOrThrow() }.isInstanceOf(CashException::class.java)
|
||||
assertThatThrownBy { flow3.resultFuture.getOrThrow() }.isInstanceOf(CashException::class.java)
|
||||
} finally {
|
||||
mockNet.stopNodes()
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,9 @@ 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.*
|
||||
import net.corda.testing.BOC
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetwork.MockNode
|
||||
@ -23,15 +25,13 @@ class CashExitFlowTests {
|
||||
private val ref = OpaqueBytes.of(0x01)
|
||||
private lateinit var bankOfCordaNode: StartedNode<MockNode>
|
||||
private lateinit var bankOfCorda: Party
|
||||
private lateinit var notaryNode: StartedNode<MockNode>
|
||||
private lateinit var notary: Party
|
||||
|
||||
@Before
|
||||
fun start() {
|
||||
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(), cordappPackages = listOf("net.corda.finance.contracts.asset"))
|
||||
notaryNode = mockNet.createNotaryNode()
|
||||
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(),
|
||||
cordappPackages = listOf("net.corda.finance.contracts.asset"))
|
||||
bankOfCordaNode = mockNet.createPartyNode(BOC.name)
|
||||
notary = notaryNode.services.getDefaultNotary()
|
||||
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
|
||||
|
||||
mockNet.runNetwork()
|
||||
|
@ -7,9 +7,8 @@ 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.BOC
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetwork.MockNode
|
||||
@ -23,16 +22,14 @@ class CashIssueFlowTests {
|
||||
private lateinit var mockNet: MockNetwork
|
||||
private lateinit var bankOfCordaNode: StartedNode<MockNode>
|
||||
private lateinit var bankOfCorda: Party
|
||||
private lateinit var notaryNode: StartedNode<MockNode>
|
||||
private lateinit var notary: Party
|
||||
|
||||
@Before
|
||||
fun start() {
|
||||
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(), cordappPackages = listOf("net.corda.finance.contracts.asset"))
|
||||
notaryNode = mockNet.createNotaryNode()
|
||||
bankOfCordaNode = mockNet.createPartyNode(BOC.name)
|
||||
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
|
||||
notary = notaryNode.services.getDefaultNotary()
|
||||
notary = mockNet.defaultNotaryIdentity
|
||||
mockNet.runNetwork()
|
||||
}
|
||||
|
||||
|
@ -26,18 +26,16 @@ class CashPaymentFlowTests {
|
||||
private val ref = OpaqueBytes.of(0x01)
|
||||
private lateinit var bankOfCordaNode: StartedNode<MockNode>
|
||||
private lateinit var bankOfCorda: Party
|
||||
private lateinit var notaryNode: StartedNode<MockNode>
|
||||
private lateinit var notary: Party
|
||||
private lateinit var aliceNode: StartedNode<MockNode>
|
||||
|
||||
@Before
|
||||
fun start() {
|
||||
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(), cordappPackages = listOf("net.corda.finance.contracts.asset"))
|
||||
notaryNode = mockNet.createNotaryNode()
|
||||
bankOfCordaNode = mockNet.createPartyNode(BOC.name)
|
||||
aliceNode = mockNet.createPartyNode(ALICE.name)
|
||||
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
|
||||
notary = notaryNode.services.getDefaultNotary()
|
||||
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture
|
||||
mockNet.runNetwork()
|
||||
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, mockNet.defaultNotaryIdentity)).resultFuture
|
||||
future.getOrThrow()
|
||||
}
|
||||
|
||||
@ -48,7 +46,7 @@ class CashPaymentFlowTests {
|
||||
|
||||
@Test
|
||||
fun `pay some cash`() {
|
||||
val payTo = notaryNode.info.chooseIdentity()
|
||||
val payTo = aliceNode.info.chooseIdentity()
|
||||
val expectedPayment = 500.DOLLARS
|
||||
val expectedChange = 1500.DOLLARS
|
||||
|
||||
@ -56,7 +54,7 @@ class CashPaymentFlowTests {
|
||||
// Register for vault updates
|
||||
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)
|
||||
val (_, vaultUpdatesBoc) = bankOfCordaNode.services.vaultService.trackBy<Cash.State>(criteria)
|
||||
val (_, vaultUpdatesBankClient) = notaryNode.services.vaultService.trackBy<Cash.State>(criteria)
|
||||
val (_, vaultUpdatesBankClient) = aliceNode.services.vaultService.trackBy<Cash.State>(criteria)
|
||||
|
||||
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expectedPayment,
|
||||
payTo)).resultFuture
|
||||
@ -88,7 +86,7 @@ class CashPaymentFlowTests {
|
||||
|
||||
@Test
|
||||
fun `pay more than we have`() {
|
||||
val payTo = notaryNode.info.chooseIdentity()
|
||||
val payTo = aliceNode.info.chooseIdentity()
|
||||
val expected = 4000.DOLLARS
|
||||
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected,
|
||||
payTo)).resultFuture
|
||||
@ -100,7 +98,7 @@ class CashPaymentFlowTests {
|
||||
|
||||
@Test
|
||||
fun `pay zero cash`() {
|
||||
val payTo = notaryNode.info.chooseIdentity()
|
||||
val payTo = aliceNode.info.chooseIdentity()
|
||||
val expected = 0.DOLLARS
|
||||
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected,
|
||||
payTo)).resultFuture
|
||||
|
@ -15,9 +15,9 @@ import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.node.services.Permissions.Companion.startFlow
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.driver.NodeHandle
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import net.corda.testing.performance.div
|
||||
import net.corda.testing.performance.startPublishingFixedRateInjector
|
||||
import net.corda.testing.performance.startReporter
|
||||
@ -102,26 +102,25 @@ class NodePerformanceTests {
|
||||
|
||||
@Test
|
||||
fun `self pay rate`() {
|
||||
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.finance")) {
|
||||
val a = startNotaryNode(
|
||||
DUMMY_NOTARY.name,
|
||||
rpcUsers = listOf(User("A", "A", setOf(startFlow<CashIssueFlow>(), startFlow<CashPaymentFlow>())))
|
||||
).getOrThrow()
|
||||
a as NodeHandle.InProcess
|
||||
val metricRegistry = startReporter(shutdownManager, a.node.services.monitoringService.metrics)
|
||||
a.rpcClientToNode().use("A", "A") { connection ->
|
||||
val notary = connection.proxy.notaryIdentities().first()
|
||||
val user = User("A", "A", setOf(startFlow<CashIssueFlow>(), startFlow<CashPaymentFlow>()))
|
||||
driver(
|
||||
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name, rpcUsers = listOf(user))),
|
||||
startNodesInProcess = true,
|
||||
extraCordappPackagesToScan = listOf("net.corda.finance")
|
||||
) {
|
||||
val notary = defaultNotaryNode.getOrThrow() as NodeHandle.InProcess
|
||||
val metricRegistry = startReporter(shutdownManager, notary.node.services.monitoringService.metrics)
|
||||
notary.rpcClientToNode().use("A", "A") { connection ->
|
||||
println("ISSUING")
|
||||
val doneFutures = (1..100).toList().parallelStream().map {
|
||||
connection.proxy.startFlow(::CashIssueFlow, 1.DOLLARS, OpaqueBytes.of(0), notary).returnValue
|
||||
connection.proxy.startFlow(::CashIssueFlow, 1.DOLLARS, OpaqueBytes.of(0), defaultNotaryIdentity).returnValue
|
||||
}.toList()
|
||||
doneFutures.transpose().get()
|
||||
println("STARTING PAYMENT")
|
||||
startPublishingFixedRateInjector(metricRegistry, 8, 5.minutes, 100L / TimeUnit.SECONDS) {
|
||||
connection.proxy.startFlow(::CashPaymentFlow, 1.DOLLARS, a.nodeInfo.chooseIdentity()).returnValue.get()
|
||||
connection.proxy.startFlow(::CashPaymentFlow, 1.DOLLARS, defaultNotaryIdentity).returnValue.get()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -13,20 +13,16 @@ import net.corda.core.internal.div
|
||||
import net.corda.core.internal.toLedgerTransaction
|
||||
import net.corda.core.serialization.SerializationFactory
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.core.utilities.seconds
|
||||
import net.corda.node.internal.cordapp.CordappLoader
|
||||
import net.corda.node.internal.cordapp.CordappProviderImpl
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.SerializationEnvironmentRule
|
||||
import net.corda.testing.driver.DriverDSLExposedInterface
|
||||
import net.corda.testing.driver.NodeHandle
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.eventually
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
@ -56,19 +52,15 @@ class AttachmentLoadingTests {
|
||||
|
||||
val bankAName = CordaX500Name("BankA", "Zurich", "CH")
|
||||
val bankBName = CordaX500Name("BankB", "Zurich", "CH")
|
||||
val notaryName = CordaX500Name("Notary", "Zurich", "CH")
|
||||
val flowInitiatorClass: Class<out FlowLogic<*>> =
|
||||
Class.forName("net.corda.finance.contracts.isolated.IsolatedDummyFlow\$Initiator", true, URLClassLoader(arrayOf(isolatedJAR)))
|
||||
.asSubclass(FlowLogic::class.java)
|
||||
|
||||
private fun DriverDSLExposedInterface.createNotaryAndTwoNodes(): List<NodeHandle> {
|
||||
val adminUser = User("admin", "admin", permissions = setOf("ALL"))
|
||||
val nodes = listOf(
|
||||
startNotaryNode(providedName = notaryName, rpcUsers = listOf(adminUser), validating = false),
|
||||
startNode(providedName = bankAName, rpcUsers = listOf(adminUser)),
|
||||
startNode(providedName = bankBName, rpcUsers = listOf(adminUser))
|
||||
).transpose().getOrThrow() // Wait for all nodes to start up.
|
||||
return nodes
|
||||
private fun DriverDSLExposedInterface.createTwoNodes(): List<NodeHandle> {
|
||||
return listOf(
|
||||
startNode(providedName = bankAName),
|
||||
startNode(providedName = bankBName)
|
||||
).transpose().getOrThrow()
|
||||
}
|
||||
|
||||
private fun DriverDSLExposedInterface.installIsolatedCordappTo(nodeName: CordaX500Name) {
|
||||
@ -81,15 +73,6 @@ class AttachmentLoadingTests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Due to cluster instability after nodes been started it may take some time to all the nodes to become available
|
||||
// *and* discover each other to reliably communicate. Hence, eventual nature of the test.
|
||||
// TODO: Remove this method and usages of it once NetworkMap service been re-worked
|
||||
private fun eventuallyPassingTest(block: () -> Unit) {
|
||||
eventually<Throwable, Unit>(30.seconds) {
|
||||
block()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var services: Services
|
||||
@ -105,9 +88,8 @@ class AttachmentLoadingTests {
|
||||
val contractClass = appClassLoader.loadClass(ISOLATED_CONTRACT_ID).asSubclass(Contract::class.java)
|
||||
val generateInitialMethod = contractClass.getDeclaredMethod("generateInitial", PartyAndReference::class.java, Integer.TYPE, Party::class.java)
|
||||
val contract = contractClass.newInstance()
|
||||
val txBuilder = generateInitialMethod.invoke(contract, PartyAndReference(DUMMY_BANK_A, OpaqueBytes(kotlin.ByteArray(1))), 1, DUMMY_NOTARY) as TransactionBuilder
|
||||
val context = SerializationFactory.defaultFactory.defaultContext
|
||||
.withClassLoader(appClassLoader)
|
||||
val txBuilder = generateInitialMethod.invoke(contract, DUMMY_BANK_A.ref(1), 1, DUMMY_NOTARY) as TransactionBuilder
|
||||
val context = SerializationFactory.defaultFactory.defaultContext.withClassLoader(appClassLoader)
|
||||
val ledgerTx = txBuilder.toLedgerTransaction(services, context)
|
||||
contract.verify(ledgerTx)
|
||||
|
||||
@ -121,24 +103,20 @@ class AttachmentLoadingTests {
|
||||
fun `test that attachments retrieved over the network are not used for code`() {
|
||||
driver(initialiseSerialization = false) {
|
||||
installIsolatedCordappTo(bankAName)
|
||||
val (_, bankA, bankB) = createNotaryAndTwoNodes()
|
||||
eventuallyPassingTest {
|
||||
val (bankA, bankB) = createTwoNodes()
|
||||
assertFailsWith<UnexpectedFlowEndException>("Party C=CH,L=Zurich,O=BankB rejected session request: Don't know net.corda.finance.contracts.isolated.IsolatedDummyFlow\$Initiator") {
|
||||
bankA.rpc.startFlowDynamic(flowInitiatorClass, bankB.nodeInfo.legalIdentities.first()).returnValue.getOrThrow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `tests that if the attachment is loaded on both sides already that a flow can run`() {
|
||||
driver(initialiseSerialization = false) {
|
||||
installIsolatedCordappTo(bankAName)
|
||||
installIsolatedCordappTo(bankBName)
|
||||
val (_, bankA, bankB) = createNotaryAndTwoNodes()
|
||||
eventuallyPassingTest {
|
||||
val (bankA, bankB) = createTwoNodes()
|
||||
bankA.rpc.startFlowDynamic(flowInitiatorClass, bankB.nodeInfo.legalIdentities.first()).returnValue.getOrThrow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,60 +11,64 @@ import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.finance.POUNDS
|
||||
import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.node.services.Permissions.Companion.startFlow
|
||||
import net.corda.node.services.Permissions.Companion.invokeRpc
|
||||
import net.corda.node.services.transactions.RaftValidatingNotaryService
|
||||
import net.corda.node.services.Permissions.Companion.startFlow
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.driver.NodeHandle
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.node.ClusterSpec
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import rx.Observable
|
||||
import java.util.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class DistributedServiceTests {
|
||||
lateinit var alice: NodeHandle
|
||||
lateinit var notaries: List<NodeHandle.OutOfProcess>
|
||||
lateinit var aliceProxy: CordaRPCOps
|
||||
lateinit var raftNotaryIdentity: Party
|
||||
lateinit var notaryStateMachines: Observable<Pair<Party, StateMachineUpdate>>
|
||||
private fun setup(runTest: () -> Unit) = driver(extraCordappPackagesToScan = listOf("net.corda.finance.contracts")) {
|
||||
// Start Alice and 3 notaries in a RAFT cluster
|
||||
val clusterSize = 3
|
||||
private lateinit var alice: NodeHandle
|
||||
private lateinit var notaryNodes: List<NodeHandle.OutOfProcess>
|
||||
private lateinit var aliceProxy: CordaRPCOps
|
||||
private lateinit var raftNotaryIdentity: Party
|
||||
private lateinit var notaryStateMachines: Observable<Pair<Party, StateMachineUpdate>>
|
||||
|
||||
private fun setup(testBlock: () -> Unit) {
|
||||
val testUser = User("test", "test", permissions = setOf(
|
||||
startFlow<CashIssueFlow>(),
|
||||
startFlow<CashPaymentFlow>(),
|
||||
invokeRpc(CordaRPCOps::nodeInfo),
|
||||
invokeRpc(CordaRPCOps::stateMachinesFeed))
|
||||
)
|
||||
val notariesFuture = startNotaryCluster(
|
||||
DUMMY_NOTARY.name.copy(commonName = RaftValidatingNotaryService.id),
|
||||
rpcUsers = listOf(testUser),
|
||||
clusterSize = clusterSize
|
||||
)
|
||||
val aliceFuture = startNode(providedName = ALICE.name, rpcUsers = listOf(testUser))
|
||||
|
||||
alice = aliceFuture.get()
|
||||
val (notaryIdentity, notaryNodes) = notariesFuture.get()
|
||||
raftNotaryIdentity = notaryIdentity
|
||||
notaries = notaryNodes.map { it as NodeHandle.OutOfProcess }
|
||||
driver(
|
||||
extraCordappPackagesToScan = listOf("net.corda.finance.contracts"),
|
||||
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name, rpcUsers = listOf(testUser), cluster = ClusterSpec.Raft(clusterSize = 3))))
|
||||
{
|
||||
alice = startNode(providedName = ALICE.name, rpcUsers = listOf(testUser)).getOrThrow()
|
||||
raftNotaryIdentity = defaultNotaryIdentity
|
||||
notaryNodes = defaultNotaryHandle.nodeHandles.getOrThrow().map { it as NodeHandle.OutOfProcess }
|
||||
|
||||
assertThat(notaryNodes).hasSize(3)
|
||||
|
||||
for (notaryNode in notaryNodes) {
|
||||
assertThat(notaryNode.nodeInfo.legalIdentities).contains(raftNotaryIdentity)
|
||||
}
|
||||
|
||||
assertEquals(notaries.size, clusterSize)
|
||||
// Check that each notary has different identity as a node.
|
||||
assertEquals(notaries.size, notaries.map { it.nodeInfo.chooseIdentity() }.toSet().size)
|
||||
assertThat(notaryNodes.flatMap { it.nodeInfo.legalIdentities - raftNotaryIdentity }.toSet()).hasSameSizeAs(notaryNodes)
|
||||
|
||||
// Connect to Alice and the notaries
|
||||
fun connectRpc(node: NodeHandle): CordaRPCOps {
|
||||
val client = node.rpcClientToNode()
|
||||
return client.start("test", "test").proxy
|
||||
}
|
||||
aliceProxy = connectRpc(alice)
|
||||
val rpcClientsToNotaries = notaries.map(::connectRpc)
|
||||
val rpcClientsToNotaries = notaryNodes.map(::connectRpc)
|
||||
notaryStateMachines = Observable.from(rpcClientsToNotaries.map { proxy ->
|
||||
proxy.stateMachinesFeed().updates.map { Pair(proxy.nodeInfo().chooseIdentity(), it) }
|
||||
}).flatMap { it.onErrorResumeNext(Observable.empty()) }.bufferUntilSubscribed()
|
||||
|
||||
runTest()
|
||||
testBlock()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Use a dummy distributed service rather than a Raft Notary Service as this test is only about Artemis' ability
|
||||
@ -106,8 +110,8 @@ class DistributedServiceTests {
|
||||
paySelf(5.POUNDS)
|
||||
}
|
||||
|
||||
// Now kill a notary
|
||||
with(notaries[0].process) {
|
||||
// Now kill a notary node
|
||||
with(notaryNodes[0].process) {
|
||||
destroy()
|
||||
waitFor()
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.driver.NodeHandle
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.node.ClusterSpec
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import org.junit.Test
|
||||
import java.util.*
|
||||
import kotlin.test.assertEquals
|
||||
@ -28,13 +30,16 @@ class RaftNotaryServiceTests {
|
||||
|
||||
@Test
|
||||
fun `detect double spend`() {
|
||||
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.testing.contracts")) {
|
||||
val (notaryParty) = startNotaryCluster(notaryName, 3).getOrThrow()
|
||||
driver(
|
||||
startNodesInProcess = true,
|
||||
extraCordappPackagesToScan = listOf("net.corda.testing.contracts"),
|
||||
notarySpecs = listOf(NotarySpec(notaryName, cluster = ClusterSpec.Raft(clusterSize = 3))))
|
||||
{
|
||||
val bankA = startNode(providedName = DUMMY_BANK_A.name).map { (it as NodeHandle.InProcess).node }.getOrThrow()
|
||||
|
||||
val inputState = issueState(bankA, notaryParty)
|
||||
val inputState = issueState(bankA, defaultNotaryIdentity)
|
||||
|
||||
val firstTxBuilder = TransactionBuilder(notaryParty)
|
||||
val firstTxBuilder = TransactionBuilder(defaultNotaryIdentity)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey))
|
||||
val firstSpendTx = bankA.services.signInitialTransaction(firstTxBuilder)
|
||||
@ -42,7 +47,7 @@ class RaftNotaryServiceTests {
|
||||
val firstSpend = bankA.services.startFlow(NotaryFlow.Client(firstSpendTx))
|
||||
firstSpend.resultFuture.getOrThrow()
|
||||
|
||||
val secondSpendBuilder = TransactionBuilder(notaryParty).withItems(inputState).run {
|
||||
val secondSpendBuilder = TransactionBuilder(defaultNotaryIdentity).withItems(inputState).run {
|
||||
val dummyState = DummyContract.SingleOwnerState(0, bankA.info.chooseIdentity())
|
||||
addOutputState(dummyState, DummyContract.PROGRAM_ID)
|
||||
addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey))
|
||||
|
@ -8,11 +8,11 @@ import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.aliceAndBob
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.contracts.DummyState
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.notaryAliceAndBob
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@ -65,7 +65,7 @@ class LargeTransactionsTest {
|
||||
val bigFile3 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024 * 3, 2)
|
||||
val bigFile4 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024 * 3, 3)
|
||||
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.testing.contracts")) {
|
||||
val (_, alice) = notaryAliceAndBob()
|
||||
val (alice, _) = aliceAndBob()
|
||||
alice.useRPC {
|
||||
val hash1 = it.uploadAttachment(bigFile1.inputStream)
|
||||
val hash2 = it.uploadAttachment(bigFile2.inputStream)
|
||||
|
@ -21,6 +21,8 @@ import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.driver.DriverDSLExposedInterface
|
||||
import net.corda.testing.driver.NodeHandle
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.node.ClusterSpec
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import java.util.*
|
||||
@ -35,16 +37,14 @@ class P2PMessagingTest {
|
||||
|
||||
@Test
|
||||
fun `communicating with a distributed service which we're part of`() {
|
||||
driver(startNodesInProcess = true) {
|
||||
val distributedService = startDistributedService()
|
||||
startDriverWithDistributedService { distributedService ->
|
||||
assertAllNodesAreUsed(distributedService, DISTRIBUTED_SERVICE_NAME, distributedService[0])
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `distributed service requests are retried if one of the nodes in the cluster goes down without sending a response`() {
|
||||
driver(startNodesInProcess = true) {
|
||||
val distributedServiceNodes = startDistributedService()
|
||||
startDriverWithDistributedService { distributedServiceNodes ->
|
||||
val alice = startAlice()
|
||||
val serviceAddress = alice.services.networkMapCache.run {
|
||||
val notaryParty = notaryIdentities.randomOrNull()!!
|
||||
@ -77,8 +77,7 @@ class P2PMessagingTest {
|
||||
|
||||
@Test
|
||||
fun `distributed service request retries are persisted across client node restarts`() {
|
||||
driver(startNodesInProcess = true) {
|
||||
val distributedServiceNodes = startDistributedService()
|
||||
startDriverWithDistributedService { distributedServiceNodes ->
|
||||
val alice = startAlice()
|
||||
val serviceAddress = alice.services.networkMapCache.run {
|
||||
val notaryParty = notaryIdentities.randomOrNull()!!
|
||||
@ -117,11 +116,10 @@ class P2PMessagingTest {
|
||||
}
|
||||
}
|
||||
|
||||
private fun DriverDSLExposedInterface.startDistributedService(): List<StartedNode<Node>> {
|
||||
return startNotaryCluster(DISTRIBUTED_SERVICE_NAME, 2)
|
||||
.getOrThrow()
|
||||
.second
|
||||
.map { (it as NodeHandle.InProcess).node }
|
||||
private fun startDriverWithDistributedService(dsl: DriverDSLExposedInterface.(List<StartedNode<Node>>) -> Unit) {
|
||||
driver(startNodesInProcess = true, notarySpecs = listOf(NotarySpec(DISTRIBUTED_SERVICE_NAME, cluster = ClusterSpec.Raft(clusterSize = 2)))) {
|
||||
dsl(defaultNotaryHandle.nodeHandles.getOrThrow().map { (it as NodeHandle.InProcess).node })
|
||||
}
|
||||
}
|
||||
|
||||
private fun DriverDSLExposedInterface.startAlice(): StartedNode<Node> {
|
||||
|
@ -17,10 +17,9 @@ import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.services.Permissions.Companion.startFlow
|
||||
import net.corda.node.services.Permissions.Companion.invokeRpc
|
||||
import net.corda.node.services.Permissions.Companion.startFlow
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.driver.driver
|
||||
import org.junit.Assume.assumeFalse
|
||||
@ -43,7 +42,6 @@ class NodeStatePersistenceTests {
|
||||
val message = Message("Hello world!")
|
||||
driver(isDebug = true, startNodesInProcess = isQuasarAgentSpecified()) {
|
||||
val nodeName = {
|
||||
startNotaryNode(DUMMY_NOTARY.name, validating = false).getOrThrow()
|
||||
val nodeHandle = startNode(rpcUsers = listOf(user)).getOrThrow()
|
||||
val nodeName = nodeHandle.nodeInfo.chooseIdentity().name
|
||||
nodeHandle.rpcClientToNode().start(user.username, user.password).use {
|
||||
|
@ -31,6 +31,7 @@ import java.security.PublicKey
|
||||
import java.util.*
|
||||
import javax.annotation.concurrent.ThreadSafe
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
class NetworkMapCacheImpl(
|
||||
networkMapCacheBase: NetworkMapCacheBaseInternal,
|
||||
@ -85,7 +86,7 @@ open class PersistentNetworkMapCache(
|
||||
override val loadDBSuccess get() = _loadDBSuccess
|
||||
|
||||
override val notaryIdentities: List<Party> = notaries.map { it.identity }
|
||||
private val validatingNotaries = notaries.mapNotNull { if (it.validating) it.identity else null }
|
||||
private val validatingNotaries = notaries.mapNotNullTo(HashSet()) { if (it.validating) it.identity else null }
|
||||
|
||||
private val nodeInfoSerializer = NodeInfoWatcher(configuration.baseDirectory,
|
||||
configuration.additionalNodeInfoPollingFrequencyMsec)
|
||||
|
@ -50,14 +50,12 @@ import kotlin.test.assertNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class CordaRPCOpsImplTest {
|
||||
|
||||
private companion object {
|
||||
val testJar = "net/corda/node/testing/test.jar"
|
||||
}
|
||||
|
||||
private lateinit var mockNet: MockNetwork
|
||||
private lateinit var aliceNode: StartedNode<MockNode>
|
||||
private lateinit var notaryNode: StartedNode<MockNode>
|
||||
private lateinit var notary: Party
|
||||
private lateinit var rpc: CordaRPCOps
|
||||
private lateinit var stateMachineUpdates: Observable<StateMachineUpdate>
|
||||
@ -69,7 +67,6 @@ class CordaRPCOpsImplTest {
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = MockNetwork(cordappPackages = listOf("net.corda.finance.contracts.asset"))
|
||||
notaryNode = mockNet.createNotaryNode(validating = false)
|
||||
aliceNode = mockNet.createNode()
|
||||
rpc = SecureCordaRPCOps(aliceNode.services, aliceNode.smm, aliceNode.database, aliceNode.services)
|
||||
CURRENT_RPC_CONTEXT.set(RpcContext(user))
|
||||
|
@ -74,14 +74,12 @@ class TestCordaService2(val appServiceHub: AppServiceHub): SingletonSerializeAsT
|
||||
class LegacyCordaService(@Suppress("UNUSED_PARAMETER") simpleServiceHub: ServiceHub) : SingletonSerializeAsToken()
|
||||
|
||||
class CordaServiceTest {
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var nodeA: StartedNode<MockNetwork.MockNode>
|
||||
private lateinit var mockNet: MockNetwork
|
||||
private lateinit var nodeA: StartedNode<MockNetwork.MockNode>
|
||||
|
||||
@Before
|
||||
fun start() {
|
||||
mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.node.internal","net.corda.finance"))
|
||||
notaryNode = mockNet.createNotaryNode()
|
||||
nodeA = mockNet.createNode()
|
||||
mockNet.startNodes()
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ import kotlin.test.assertTrue
|
||||
* We assume that Alice and Bob already found each other via some market, and have agreed the details already.
|
||||
*/
|
||||
@RunWith(Parameterized::class)
|
||||
class TwoPartyTradeFlowTests(val anonymous: Boolean) {
|
||||
class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
|
||||
companion object {
|
||||
private val cordappPackages = listOf("net.corda.finance.contracts")
|
||||
@JvmStatic
|
||||
@ -93,7 +93,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
|
||||
// allow interruption half way through.
|
||||
mockNet = MockNetwork(threadPerNode = true, cordappPackages = cordappPackages)
|
||||
ledger(MockServices(cordappPackages), initialiseSerialization = false) {
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val notaryNode = mockNet.defaultNotaryNode
|
||||
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
||||
val bobNode = mockNet.createPartyNode(BOB_NAME)
|
||||
val bankNode = mockNet.createPartyNode(BOC_NAME)
|
||||
@ -143,7 +143,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
|
||||
fun `trade cash for commercial paper fails using soft locking`() {
|
||||
mockNet = MockNetwork(threadPerNode = true, cordappPackages = cordappPackages)
|
||||
ledger(MockServices(cordappPackages), initialiseSerialization = false) {
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val notaryNode = mockNet.defaultNotaryNode
|
||||
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
||||
val bobNode = mockNet.createPartyNode(BOB_NAME)
|
||||
val bankNode = mockNet.createPartyNode(BOC_NAME)
|
||||
@ -199,7 +199,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
|
||||
fun `shutdown and restore`() {
|
||||
mockNet = MockNetwork(cordappPackages = cordappPackages)
|
||||
ledger(MockServices(cordappPackages), initialiseSerialization = false) {
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val notaryNode = mockNet.defaultNotaryNode
|
||||
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
||||
var bobNode = mockNet.createPartyNode(BOB_NAME)
|
||||
val bankNode = mockNet.createPartyNode(BOC_NAME)
|
||||
@ -292,7 +292,8 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
|
||||
|
||||
// Creates a mock node with an overridden storage service that uses a RecordingMap, that lets us test the order
|
||||
// of gets and puts.
|
||||
private fun makeNodeWithTracking(name: CordaX500Name): StartedNode<MockNetwork.MockNode> {
|
||||
private fun makeNodeWithTracking(
|
||||
name: CordaX500Name): StartedNode<MockNetwork.MockNode> {
|
||||
// Create a node in the mock network ...
|
||||
return mockNet.createNode(MockNodeParameters(legalName = name), nodeFactory = { args ->
|
||||
object : MockNetwork.MockNode(args) {
|
||||
@ -307,7 +308,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
|
||||
@Test
|
||||
fun `check dependencies of sale asset are resolved`() {
|
||||
mockNet = MockNetwork(cordappPackages = cordappPackages)
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val notaryNode = mockNet.defaultNotaryNode
|
||||
val aliceNode = makeNodeWithTracking(ALICE_NAME)
|
||||
val bobNode = makeNodeWithTracking(BOB_NAME)
|
||||
val bankNode = makeNodeWithTracking(BOC_NAME)
|
||||
@ -413,7 +414,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
|
||||
@Test
|
||||
fun `track works`() {
|
||||
mockNet = MockNetwork(cordappPackages = cordappPackages)
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val notaryNode = mockNet.defaultNotaryNode
|
||||
val aliceNode = makeNodeWithTracking(ALICE_NAME)
|
||||
val bobNode = makeNodeWithTracking(BOB_NAME)
|
||||
val bankNode = makeNodeWithTracking(BOC_NAME)
|
||||
@ -568,7 +569,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
|
||||
aliceError: Boolean,
|
||||
expectedMessageSubstring: String
|
||||
) {
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val notaryNode = mockNet.defaultNotaryNode
|
||||
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
||||
val bobNode = mockNet.createPartyNode(BOB_NAME)
|
||||
val bankNode = mockNet.createPartyNode(BOC_NAME)
|
||||
|
@ -1,7 +1,5 @@
|
||||
package net.corda.node.services
|
||||
|
||||
import com.nhaarman.mockito_kotlin.doReturn
|
||||
import com.nhaarman.mockito_kotlin.whenever
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.generateKeyPair
|
||||
import net.corda.core.flows.NotaryChangeFlow
|
||||
@ -15,14 +13,10 @@ import net.corda.core.transactions.WireTransaction
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.seconds
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.node.services.config.NotaryConfig
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.getTestPartyAndCertificate
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNodeParameters
|
||||
import net.corda.testing.node.MockNetwork.NotarySpec
|
||||
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@ -42,23 +36,17 @@ class NotaryChangeTests {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
|
||||
val (oldNotaryNode, newNotaryNode) = listOf(
|
||||
createUnstartedNotary(DUMMY_NOTARY.name),
|
||||
createUnstartedNotary(DUMMY_NOTARY.name.copy(organisation = "Dummy Notary 2"))
|
||||
).map { it.start() }
|
||||
this.oldNotaryNode = oldNotaryNode
|
||||
val oldNotaryName = DUMMY_REGULATOR.name
|
||||
mockNet = MockNetwork(
|
||||
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name), NotarySpec(oldNotaryName)),
|
||||
cordappPackages = listOf("net.corda.testing.contracts")
|
||||
)
|
||||
clientNodeA = mockNet.createNode()
|
||||
clientNodeB = mockNet.createNode()
|
||||
oldNotaryParty = newNotaryNode.services.networkMapCache.getNotary(DUMMY_NOTARY.name)!!
|
||||
newNotaryParty = newNotaryNode.services.networkMapCache.getNotary(DUMMY_NOTARY.name.copy(organisation = "Dummy Notary 2"))!!
|
||||
}
|
||||
|
||||
private fun createUnstartedNotary(name: CordaX500Name): MockNetwork.MockNode {
|
||||
return mockNet.createUnstartedNode(MockNodeParameters(
|
||||
legalName = name,
|
||||
configOverrides = { doReturn(NotaryConfig(validating = true)).whenever(it).notary }
|
||||
))
|
||||
oldNotaryNode = mockNet.notaryNodes[1]
|
||||
mockNet.runNetwork() // Clear network map registration messages
|
||||
newNotaryParty = clientNodeA.services.networkMapCache.getNotary(DUMMY_NOTARY.name)!!
|
||||
oldNotaryParty = clientNodeA.services.networkMapCache.getNotary(oldNotaryName)!!
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -35,7 +35,6 @@ class ScheduledFlowTests {
|
||||
}
|
||||
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var nodeA: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var nodeB: StartedNode<MockNetwork.MockNode>
|
||||
|
||||
@ -94,7 +93,6 @@ class ScheduledFlowTests {
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.testing.contracts"))
|
||||
notaryNode = mockNet.createNotaryNode()
|
||||
val a = mockNet.createUnstartedNode()
|
||||
val b = mockNet.createUnstartedNode()
|
||||
|
||||
|
@ -38,13 +38,13 @@ class NetworkMapCacheTest {
|
||||
|
||||
@Test
|
||||
fun `getNodeByLegalIdentity`() {
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(ALICE.name)
|
||||
val notaryCache: NetworkMapCache = notaryNode.services.networkMapCache
|
||||
val bobNode = mockNet.createPartyNode(BOB.name)
|
||||
val bobCache: NetworkMapCache = bobNode.services.networkMapCache
|
||||
val expected = aliceNode.info
|
||||
|
||||
mockNet.runNetwork()
|
||||
val actual = notaryNode.database.transaction { notaryCache.getNodeByLegalIdentity(aliceNode.info.chooseIdentity()) }
|
||||
val actual = bobNode.database.transaction { bobCache.getNodeByLegalIdentity(aliceNode.info.chooseIdentity()) }
|
||||
assertEquals(expected, actual)
|
||||
|
||||
// TODO: Should have a test case with anonymous lookup
|
||||
@ -52,30 +52,30 @@ class NetworkMapCacheTest {
|
||||
|
||||
@Test
|
||||
fun `getPeerByLegalName`() {
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(ALICE.name)
|
||||
val notaryCache: NetworkMapCache = notaryNode.services.networkMapCache
|
||||
val bobNode = mockNet.createPartyNode(BOB.name)
|
||||
val bobCache: NetworkMapCache = bobNode.services.networkMapCache
|
||||
val expected = aliceNode.info.legalIdentities.single()
|
||||
|
||||
mockNet.runNetwork()
|
||||
val actual = notaryNode.database.transaction { notaryCache.getPeerByLegalName(ALICE.name) }
|
||||
val actual = bobNode.database.transaction { bobCache.getPeerByLegalName(ALICE.name) }
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `remove node from cache`() {
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(ALICE.name)
|
||||
val notaryLegalIdentity = notaryNode.info.chooseIdentity()
|
||||
val bobNode = mockNet.createPartyNode(BOB.name)
|
||||
val bobLegalIdentity = bobNode.info.chooseIdentity()
|
||||
val alice = aliceNode.info.chooseIdentity()
|
||||
val notaryCache = notaryNode.services.networkMapCache
|
||||
val bobCache = bobNode.services.networkMapCache
|
||||
mockNet.runNetwork()
|
||||
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)
|
||||
bobNode.database.transaction {
|
||||
assertThat(bobCache.getNodeByLegalIdentity(alice) != null)
|
||||
bobCache.removeNode(aliceNode.info)
|
||||
assertThat(bobCache.getNodeByLegalIdentity(alice) == null)
|
||||
assertThat(bobCache.getNodeByLegalIdentity(bobLegalIdentity) != null)
|
||||
assertThat(bobCache.getNodeByLegalName(alice.name) == null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,9 +43,7 @@ class NodeSchemaServiceTest {
|
||||
@Test
|
||||
fun `auto scanning of custom schemas for testing with Driver`() {
|
||||
driver(startNodesInProcess = true) {
|
||||
val node = startNode()
|
||||
val nodeHandle = node.getOrThrow()
|
||||
val result = nodeHandle.rpc.startFlow(::MappedSchemasFlow)
|
||||
val result = defaultNotaryNode.getOrThrow().rpc.startFlow(::MappedSchemasFlow)
|
||||
val mappedSchemas = result.returnValue.getOrThrow()
|
||||
assertTrue(mappedSchemas.contains(TestSchema.name))
|
||||
}
|
||||
@ -54,11 +52,12 @@ class NodeSchemaServiceTest {
|
||||
@Test
|
||||
fun `custom schemas are loaded eagerly`() {
|
||||
val expected = setOf("PARENTS", "CHILDREN")
|
||||
assertEquals<Set<*>>(expected, driver {
|
||||
(startNode(startInSameProcess = true).getOrThrow() as NodeHandle.InProcess).node.database.transaction {
|
||||
val tables = driver(startNodesInProcess = true) {
|
||||
(defaultNotaryNode.getOrThrow() as NodeHandle.InProcess).node.database.transaction {
|
||||
session.createNativeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES").list()
|
||||
}
|
||||
}.toMutableSet().apply { retainAll(expected) })
|
||||
}
|
||||
assertEquals<Set<*>>(expected, tables.toMutableSet().apply { retainAll(expected) })
|
||||
}
|
||||
|
||||
@StartableByRPC
|
||||
|
@ -74,8 +74,8 @@ class FlowFrameworkTests {
|
||||
fun start() {
|
||||
mockNet = MockNetwork(
|
||||
servicePeerAllocationStrategy = RoundRobin(),
|
||||
cordappPackages = listOf("net.corda.finance.contracts", "net.corda.testing.contracts"))
|
||||
val notary = mockNet.createNotaryNode()
|
||||
cordappPackages = listOf("net.corda.finance.contracts", "net.corda.testing.contracts")
|
||||
)
|
||||
aliceNode = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME))
|
||||
bobNode = mockNet.createNode(MockNodeParameters(legalName = BOB_NAME))
|
||||
|
||||
@ -84,7 +84,7 @@ class FlowFrameworkTests {
|
||||
// Extract identities
|
||||
alice = aliceNode.info.singleIdentity()
|
||||
bob = bobNode.info.singleIdentity()
|
||||
notaryIdentity = notary.services.getDefaultNotary()
|
||||
notaryIdentity = aliceNode.services.getDefaultNotary()
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -14,10 +14,13 @@ import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.seconds
|
||||
import net.corda.node.services.api.StartedNodeServices
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.ALICE_NAME
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNodeParameters
|
||||
import net.corda.testing.singleIdentity
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@ -28,20 +31,19 @@ import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
class NotaryServiceTests {
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var notaryServices: StartedNodeServices
|
||||
lateinit var aliceServices: StartedNodeServices
|
||||
lateinit var notary: Party
|
||||
lateinit var alice: Party
|
||||
private lateinit var mockNet: MockNetwork
|
||||
private lateinit var notaryServices: StartedNodeServices
|
||||
private lateinit var aliceServices: StartedNodeServices
|
||||
private lateinit var notary: Party
|
||||
private lateinit var alice: Party
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
|
||||
val notaryNode = mockNet.createNotaryNode(validating = false)
|
||||
aliceServices = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME)).services
|
||||
mockNet.runNetwork() // Clear network map registration messages
|
||||
notaryServices = notaryNode.services
|
||||
notary = notaryServices.getDefaultNotary()
|
||||
notaryServices = mockNet.defaultNotaryNode.services //TODO get rid of that
|
||||
notary = aliceServices.getDefaultNotary()
|
||||
alice = aliceServices.myInfo.singleIdentity()
|
||||
}
|
||||
|
||||
@ -155,7 +157,7 @@ class NotaryServiceTests {
|
||||
return future
|
||||
}
|
||||
|
||||
fun issueState(services: ServiceHub, identity: Party): StateAndRef<*> {
|
||||
private fun issueState(services: ServiceHub, identity: Party): StateAndRef<*> {
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notary, identity.ref(0))
|
||||
val signedByNode = services.signInitialTransaction(tx)
|
||||
val stx = notaryServices.addSignature(signedByNode, notary.owningKey)
|
||||
|
@ -15,10 +15,13 @@ import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.services.api.StartedNodeServices
|
||||
import net.corda.node.services.issueInvalidState
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.ALICE_NAME
|
||||
import net.corda.testing.MEGA_CORP_KEY
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNodeParameters
|
||||
import net.corda.testing.singleIdentity
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@ -28,21 +31,20 @@ import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
class ValidatingNotaryServiceTests {
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var notaryServices: StartedNodeServices
|
||||
lateinit var aliceServices: StartedNodeServices
|
||||
lateinit var notary: Party
|
||||
lateinit var alice: Party
|
||||
private lateinit var mockNet: MockNetwork
|
||||
private lateinit var notaryServices: StartedNodeServices
|
||||
private lateinit var aliceServices: StartedNodeServices
|
||||
private lateinit var notary: Party
|
||||
private lateinit var alice: Party
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
|
||||
val notaryNode = mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME))
|
||||
mockNet.runNetwork() // Clear network map registration messages
|
||||
notaryServices = notaryNode.services
|
||||
notaryServices = mockNet.defaultNotaryNode.services
|
||||
aliceServices = aliceNode.services
|
||||
notary = notaryServices.getDefaultNotary()
|
||||
notary = mockNet.defaultNotaryIdentity
|
||||
alice = aliceNode.info.singleIdentity()
|
||||
}
|
||||
|
||||
@ -97,7 +99,7 @@ class ValidatingNotaryServiceTests {
|
||||
return future
|
||||
}
|
||||
|
||||
fun issueState(serviceHub: ServiceHub, identity: Party): StateAndRef<*> {
|
||||
private fun issueState(serviceHub: ServiceHub, identity: Party): StateAndRef<*> {
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notary, identity.ref(0))
|
||||
val signedByNode = serviceHub.signInitialTransaction(tx)
|
||||
val stx = notaryServices.addSignature(signedByNode, notary.owningKey)
|
||||
|
@ -7,7 +7,6 @@ import net.corda.node.services.Permissions.Companion.startFlow
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_BANK_B
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.driver.PortAllocation
|
||||
import net.corda.testing.driver.driver
|
||||
import org.junit.Test
|
||||
@ -27,11 +26,10 @@ class AttachmentDemoTest {
|
||||
invokeRpc(CordaRPCOps::wellKnownPartyFromX500Name),
|
||||
invokeRpc(CordaRPCOps::internalVerifiedTransactionsFeed)
|
||||
)))
|
||||
val (_, nodeA, nodeB) = listOf(
|
||||
startNotaryNode(DUMMY_NOTARY.name, validating = false),
|
||||
val (nodeA, nodeB) = listOf(
|
||||
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = demoUser, maximumHeapSize = "1g"),
|
||||
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser, maximumHeapSize = "1g"))
|
||||
.map { it.getOrThrow() }
|
||||
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser, maximumHeapSize = "1g")
|
||||
).map { it.getOrThrow() }
|
||||
startWebserver(nodeB).getOrThrow()
|
||||
|
||||
val senderThread = supplyAsync {
|
||||
|
@ -4,7 +4,6 @@ import net.corda.core.internal.div
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_BANK_B
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.driver.driver
|
||||
|
||||
/**
|
||||
@ -14,7 +13,6 @@ import net.corda.testing.driver.driver
|
||||
fun main(args: Array<String>) {
|
||||
val demoUser = listOf(User("demo", "demo", setOf("StartFlow.net.corda.flows.FinalityFlow")))
|
||||
driver(isDebug = true, driverDirectory = "build" / "attachment-demo-nodes") {
|
||||
startNotaryNode(DUMMY_NOTARY.name, validating = false)
|
||||
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = demoUser)
|
||||
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser)
|
||||
waitForAllNodesToFinish()
|
||||
|
@ -2,10 +2,8 @@ package net.corda.bank
|
||||
|
||||
import net.corda.bank.api.BankOfCordaClientApi
|
||||
import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams
|
||||
import net.corda.core.internal.concurrent.transpose
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.testing.BOC
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.driver.driver
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertTrue
|
||||
@ -13,14 +11,13 @@ import kotlin.test.assertTrue
|
||||
class BankOfCordaHttpAPITest {
|
||||
@Test
|
||||
fun `issuer flow via Http`() {
|
||||
driver(isDebug = true, extraCordappPackagesToScan = listOf("net.corda.finance")) {
|
||||
val (_, bocNode) = listOf(
|
||||
startNotaryNode(providedName = DUMMY_NOTARY.name),
|
||||
driver(extraCordappPackagesToScan = listOf("net.corda.finance"), isDebug = true) {
|
||||
val (bocNode) = listOf(
|
||||
startNode(providedName = BOC.name),
|
||||
startNode(providedName = BIGCORP_LEGAL_NAME)
|
||||
).transpose().getOrThrow()
|
||||
).map { it.getOrThrow() }
|
||||
val bocApiAddress = startWebserver(bocNode).getOrThrow().listenAddress
|
||||
val issueRequestParams = IssueRequestParams(1000, "USD", BIGCORP_LEGAL_NAME, "1", BOC.name, DUMMY_NOTARY.name)
|
||||
val issueRequestParams = IssueRequestParams(1000, "USD", BIGCORP_LEGAL_NAME, "1", BOC.name, defaultNotaryIdentity.name)
|
||||
assertTrue(BankOfCordaClientApi(bocApiAddress).requestWebIssue(issueRequestParams))
|
||||
}
|
||||
}
|
||||
|
@ -23,12 +23,12 @@ class BankOfCordaRPCClientTest {
|
||||
invokeRpc(CordaRPCOps::wellKnownPartyFromX500Name),
|
||||
invokeRpc(CordaRPCOps::notaryIdentities)
|
||||
)
|
||||
driver(extraCordappPackagesToScan = listOf("net.corda.finance"), dsl = {
|
||||
driver(extraCordappPackagesToScan = listOf("net.corda.finance"), isDebug = true) {
|
||||
val bocManager = User("bocManager", "password1", permissions = setOf(
|
||||
startFlow<CashIssueAndPaymentFlow>()) + commonPermissions)
|
||||
val bigCorpCFO = User("bigCorpCFO", "password2", permissions = emptySet<String>() + commonPermissions)
|
||||
val (nodeBankOfCorda, nodeBigCorporation) = listOf(
|
||||
startNotaryNode(BOC.name, rpcUsers = listOf(bocManager), validating = false),
|
||||
startNode(providedName = BOC.name, rpcUsers = listOf(bocManager)),
|
||||
startNode(providedName = BIGCORP_LEGAL_NAME, rpcUsers = listOf(bigCorpCFO))
|
||||
).map { it.getOrThrow() }
|
||||
|
||||
@ -51,12 +51,11 @@ class BankOfCordaRPCClientTest {
|
||||
|
||||
// Kick-off actual Issuer Flow
|
||||
val anonymous = true
|
||||
val notary = bocProxy.notaryIdentities().first()
|
||||
bocProxy.startFlow(::CashIssueAndPaymentFlow,
|
||||
1000.DOLLARS, BIG_CORP_PARTY_REF,
|
||||
bigCorporation,
|
||||
anonymous,
|
||||
notary).returnValue.getOrThrow()
|
||||
defaultNotaryIdentity).returnValue.getOrThrow()
|
||||
|
||||
// Check Bank of Corda Vault Updates
|
||||
vaultUpdatesBoc.expectEvents {
|
||||
@ -84,6 +83,6 @@ class BankOfCordaRPCClientTest {
|
||||
}
|
||||
)
|
||||
}
|
||||
}, isDebug = true)
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,6 @@ import net.corda.finance.flows.CashExitFlow
|
||||
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
||||
import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.node.services.Permissions.Companion.startFlow
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.BOC
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
@ -58,7 +57,6 @@ private class BankOfCordaDriver {
|
||||
when (role) {
|
||||
Role.ISSUER -> {
|
||||
driver(isDebug = true, extraCordappPackagesToScan = listOf("net.corda.finance.contracts.asset")) {
|
||||
startNotaryNode(providedName = DUMMY_NOTARY.name, validating = true)
|
||||
val bankUser = User(
|
||||
BANK_USERNAME,
|
||||
"test",
|
||||
@ -83,7 +81,7 @@ private class BankOfCordaDriver {
|
||||
}
|
||||
else -> {
|
||||
val requestParams = IssueRequestParams(options.valueOf(quantity), options.valueOf(currency), BIGCORP_LEGAL_NAME,
|
||||
"1", BOC.name, DUMMY_NOTARY.name.copy(commonName = ValidatingNotaryService.id))
|
||||
"1", BOC.name, DUMMY_NOTARY.name)
|
||||
when(role) {
|
||||
Role.ISSUE_CASH_RPC -> {
|
||||
println("Requesting Cash via RPC ...")
|
||||
|
@ -3,7 +3,6 @@ package net.corda.irs
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_BANK_B
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.driver.driver
|
||||
|
||||
/**
|
||||
@ -11,17 +10,17 @@ import net.corda.testing.driver.driver
|
||||
* Do not use in a production environment.
|
||||
*/
|
||||
fun main(args: Array<String>) {
|
||||
driver(dsl = {
|
||||
val (controller, nodeA, nodeB) = listOf(
|
||||
startNotaryNode(DUMMY_NOTARY.name, validating = false),
|
||||
driver(useTestClock = true, isDebug = true) {
|
||||
val (nodeA, nodeB) = listOf(
|
||||
startNode(providedName = DUMMY_BANK_A.name),
|
||||
startNode(providedName = DUMMY_BANK_B.name))
|
||||
.map { it.getOrThrow() }
|
||||
startNode(providedName = DUMMY_BANK_B.name)
|
||||
).map { it.getOrThrow() }
|
||||
val controller = defaultNotaryNode.getOrThrow()
|
||||
|
||||
startWebserver(controller)
|
||||
startWebserver(nodeA)
|
||||
startWebserver(nodeB)
|
||||
|
||||
waitForAllNodesToFinish()
|
||||
}, useTestClock = true, isDebug = true)
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.JsonDeserializer
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import net.corda.client.jackson.JacksonSupport
|
||||
import net.corda.client.rpc.CordaRPCClient
|
||||
import net.corda.core.contracts.UniqueIdentifier
|
||||
import net.corda.core.identity.Party
|
||||
@ -24,6 +25,7 @@ import net.corda.nodeapi.User
|
||||
import net.corda.test.spring.springDriver
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.http.HttpApi
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import org.apache.commons.io.IOUtils
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
@ -44,11 +46,17 @@ class IRSDemoTest : IntegrationTestCategory {
|
||||
|
||||
@Test
|
||||
fun `runs IRS demo`() {
|
||||
springDriver(useTestClock = true, isDebug = true, extraCordappPackagesToScan = listOf("net.corda.irs")) {
|
||||
val (controller, nodeA, nodeB) = listOf(
|
||||
startNotaryNode(DUMMY_NOTARY.name, validating = true, rpcUsers = rpcUsers),
|
||||
springDriver(
|
||||
useTestClock = true,
|
||||
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name, rpcUsers = rpcUsers)),
|
||||
isDebug = true,
|
||||
extraCordappPackagesToScan = listOf("net.corda.irs")
|
||||
) {
|
||||
val (nodeA, nodeB) = listOf(
|
||||
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = rpcUsers),
|
||||
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = rpcUsers)).map { it.getOrThrow() }
|
||||
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = rpcUsers)
|
||||
).map { it.getOrThrow() }
|
||||
val controller = defaultNotaryNode.getOrThrow()
|
||||
|
||||
log.info("All nodes started")
|
||||
|
||||
@ -61,7 +69,7 @@ class IRSDemoTest : IntegrationTestCategory {
|
||||
log.info("All webservers started")
|
||||
|
||||
val (controllerApi, nodeAApi, nodeBApi) = listOf(controller, nodeA, nodeB).zip(listOf(controllerAddr, nodeAAddr, nodeBAddr)).map {
|
||||
val mapper = net.corda.client.jackson.JacksonSupport.createDefaultMapper(it.first.rpc)
|
||||
val mapper = JacksonSupport.createDefaultMapper(it.first.rpc)
|
||||
registerFinanceJSONMappers(mapper)
|
||||
registerIRSModule(mapper)
|
||||
HttpApi.fromHostAndPort(it.second, "api/irs", mapper = mapper)
|
||||
@ -86,7 +94,9 @@ class IRSDemoTest : IntegrationTestCategory {
|
||||
}
|
||||
}
|
||||
|
||||
fun getFloatingLegFixCount(nodeApi: HttpApi) = getTrades(nodeApi)[0].calculation.floatingLegPaymentSchedule.count { it.value.rate.ratioUnit != null }
|
||||
private fun getFloatingLegFixCount(nodeApi: HttpApi): Int {
|
||||
return getTrades(nodeApi)[0].calculation.floatingLegPaymentSchedule.count { it.value.rate.ratioUnit != null }
|
||||
}
|
||||
|
||||
private fun getFixingDateObservable(config: NodeConfiguration): Observable<LocalDate?> {
|
||||
val client = CordaRPCClient(config.rpcAddress!!)
|
||||
|
@ -6,6 +6,7 @@ import net.corda.core.internal.concurrent.fork
|
||||
import net.corda.core.internal.concurrent.map
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.testing.driver.*
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import java.net.ConnectException
|
||||
@ -41,6 +42,7 @@ fun <A> springDriver(
|
||||
useTestClock: Boolean = defaultParameters.useTestClock,
|
||||
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
|
||||
startNodesInProcess: Boolean = defaultParameters.startNodesInProcess,
|
||||
notarySpecs: List<NotarySpec>,
|
||||
extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan,
|
||||
dsl: SpringDriverExposedDSLInterface.() -> A
|
||||
) = genericDriver(
|
||||
@ -54,9 +56,9 @@ fun <A> springDriver(
|
||||
initialiseSerialization = initialiseSerialization,
|
||||
startNodesInProcess = startNodesInProcess,
|
||||
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
||||
notarySpecs = notarySpecs,
|
||||
driverDslWrapper = { driverDSL:DriverDSL -> SpringBootDriverDSL(driverDSL) },
|
||||
coerce = { it },
|
||||
dsl = dsl
|
||||
coerce = { it }, dsl = dsl
|
||||
)
|
||||
|
||||
data class SpringBootDriverDSL(
|
||||
|
@ -31,7 +31,6 @@ import java.util.*
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.CompletableFuture.allOf
|
||||
|
||||
|
||||
/**
|
||||
* A simulation in which banks execute interest rate swaps with each other, including the fixing events.
|
||||
*/
|
||||
@ -140,8 +139,6 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
|
||||
node1.internals.registerInitiatedFlow(FixingFlow.Fixer::class.java)
|
||||
node2.internals.registerInitiatedFlow(FixingFlow.Fixer::class.java)
|
||||
|
||||
val notaryId = notary.info.legalIdentities[0]
|
||||
|
||||
@InitiatingFlow
|
||||
class StartDealFlow(val otherParty: Party,
|
||||
val payload: AutoOffer) : FlowLogic<SignedTransaction>() {
|
||||
@ -166,7 +163,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
|
||||
|
||||
val instigator = StartDealFlow(
|
||||
node2.info.chooseIdentity(),
|
||||
AutoOffer(notaryId, irs)) // TODO Pass notary as parameter to Simulation.
|
||||
AutoOffer(mockNet.defaultNotaryIdentity, irs)) // TODO Pass notary as parameter to Simulation.
|
||||
val instigatorTxFuture = node1.services.startFlow(instigator).resultFuture
|
||||
|
||||
return allOf(instigatorTxFuture.toCompletableFuture(), acceptorTxFuture).thenCompose { instigatorTxFuture.toCompletableFuture() }
|
||||
|
@ -9,7 +9,6 @@ import net.corda.finance.utils.CityDatabase
|
||||
import net.corda.irs.api.NodeInterestRates
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.node.services.statemachine.StateMachineManager
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.DUMMY_REGULATOR
|
||||
import net.corda.testing.node.*
|
||||
import net.corda.testing.node.MockNetwork.MockNode
|
||||
@ -71,14 +70,13 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
||||
networkSendManuallyPumped = networkSendManuallyPumped,
|
||||
threadPerNode = runAsync,
|
||||
cordappPackages = listOf("net.corda.irs.contract", "net.corda.finance.contract", "net.corda.irs"))
|
||||
val notary = mockNet.createNotaryNode(defaultParams.copy(legalName = DUMMY_NOTARY.name), false)
|
||||
// TODO: Regulatory nodes don't actually exist properly, this is a last minute demo request.
|
||||
// So we just fire a message at a node that doesn't know how to handle it, and it'll ignore it.
|
||||
// But that's fine for visualisation purposes.
|
||||
val regulators = listOf(mockNet.createUnstartedNode(defaultParams.copy(legalName = DUMMY_REGULATOR.name)))
|
||||
val ratesOracle = mockNet.createUnstartedNode(defaultParams.copy(legalName = RatesOracleNode.RATES_SERVICE_NAME), ::RatesOracleNode)
|
||||
// All nodes must be in one of these two lists for the purposes of the visualiser tool.
|
||||
val serviceProviders: List<MockNode> = listOf(notary.internals, ratesOracle)
|
||||
val serviceProviders: List<MockNode> = listOf(mockNet.defaultNotaryNode.internals, ratesOracle)
|
||||
val banks: List<MockNode> = bankLocations.mapIndexed { i, (city, country) ->
|
||||
val legalName = CordaX500Name(organisation = "Bank ${'A' + i}", locality = city, country = country)
|
||||
// Use deterministic seeds so the simulation is stable. Needed so that party owning keys are stable.
|
||||
|
@ -3,7 +3,9 @@ package net.corda.vega
|
||||
import com.opengamma.strata.product.common.BuySell
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_BANK_B
|
||||
import net.corda.testing.IntegrationTestCategory
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.http.HttpApi
|
||||
import net.corda.vega.api.PortfolioApi
|
||||
@ -27,7 +29,6 @@ class SimmValuationTest : IntegrationTestCategory {
|
||||
@Test
|
||||
fun `runs SIMM valuation demo`() {
|
||||
driver(isDebug = true, extraCordappPackagesToScan = listOf("net.corda.vega.contracts")) {
|
||||
startNotaryNode(DUMMY_NOTARY.name, validating = false).getOrThrow()
|
||||
val nodeAFuture = startNode(providedName = nodeALegalName)
|
||||
val nodeBFuture = startNode(providedName = nodeBLegalName)
|
||||
val (nodeA, nodeB) = listOf(nodeAFuture, nodeBFuture).map { it.getOrThrow() }
|
||||
|
@ -4,7 +4,6 @@ import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_BANK_B
|
||||
import net.corda.testing.DUMMY_BANK_C
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.driver.driver
|
||||
|
||||
/**
|
||||
@ -13,17 +12,17 @@ import net.corda.testing.driver.driver
|
||||
* via the web api.
|
||||
*/
|
||||
fun main(args: Array<String>) {
|
||||
driver(dsl = {
|
||||
val notaryFuture = startNotaryNode(DUMMY_NOTARY.name, validating = false)
|
||||
val nodeAFuture = startNode(providedName = DUMMY_BANK_A.name)
|
||||
val nodeBFuture = startNode(providedName = DUMMY_BANK_B.name)
|
||||
val nodeCFuture = startNode(providedName = DUMMY_BANK_C.name)
|
||||
val (nodeA, nodeB, nodeC) = listOf(nodeAFuture, nodeBFuture, nodeCFuture, notaryFuture).map { it.getOrThrow() }
|
||||
driver(isDebug = true) {
|
||||
val (nodeA, nodeB, nodeC) = listOf(
|
||||
startNode(providedName = DUMMY_BANK_A.name),
|
||||
startNode(providedName = DUMMY_BANK_B.name),
|
||||
startNode(providedName = DUMMY_BANK_C.name)
|
||||
).map { it.getOrThrow() }
|
||||
|
||||
startWebserver(nodeA)
|
||||
startWebserver(nodeB)
|
||||
startWebserver(nodeC)
|
||||
|
||||
waitForAllNodesToFinish()
|
||||
}, isDebug = true)
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,10 @@ import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.node.services.Permissions.Companion.all
|
||||
import net.corda.node.services.Permissions.Companion.startFlow
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.BOC
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_BANK_B
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.driver.NodeHandle
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.driver.poll
|
||||
@ -30,8 +33,7 @@ class TraderDemoTest {
|
||||
startFlow<CommercialPaperIssueFlow>(),
|
||||
all()))
|
||||
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.finance")) {
|
||||
val (_, nodeA, nodeB, bankNode) = listOf(
|
||||
startNotaryNode(DUMMY_NOTARY.name, validating = false),
|
||||
val (nodeA, nodeB, bankNode) = listOf(
|
||||
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = listOf(demoUser)),
|
||||
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = listOf(demoUser)),
|
||||
startNode(providedName = BOC.name, rpcUsers = listOf(bankUser))
|
||||
|
@ -8,7 +8,6 @@ import net.corda.nodeapi.User
|
||||
import net.corda.testing.BOC
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_BANK_B
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.traderdemo.flow.CommercialPaperIssueFlow
|
||||
import net.corda.traderdemo.flow.SellerFlow
|
||||
@ -27,7 +26,6 @@ fun main(args: Array<String>) {
|
||||
val user = User("user1", "test", permissions = setOf(startFlow<CashIssueFlow>(),
|
||||
startFlow<CommercialPaperIssueFlow>(),
|
||||
startFlow<SellerFlow>()))
|
||||
startNotaryNode(DUMMY_NOTARY.name, validating = false)
|
||||
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = demoUser)
|
||||
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser)
|
||||
startNode(providedName = BOC.name, rpcUsers = listOf(user))
|
||||
|
@ -290,7 +290,6 @@ class FlowStackSnapshotTest {
|
||||
@Test
|
||||
fun `flowStackSnapshot object is serializable`() {
|
||||
val mockNet = MockNetwork(threadPerNode = true)
|
||||
mockNet.createNotaryNode()
|
||||
val node = mockNet.createPartyNode()
|
||||
node.internals.registerInitiatedFlow(DummyFlow::class.java)
|
||||
node.services.startFlow(FlowStackSnapshotSerializationTestingFlow()).resultFuture.get()
|
||||
|
@ -7,7 +7,6 @@ import net.corda.core.internal.readLines
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.internal.NodeStartup
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.DUMMY_REGULATOR
|
||||
import net.corda.testing.ProjectStructure.projectRootDir
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
@ -18,7 +17,6 @@ import java.util.concurrent.ScheduledExecutorService
|
||||
class DriverTests {
|
||||
|
||||
companion object {
|
||||
|
||||
private val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2)
|
||||
|
||||
private fun nodeMustBeUp(handleFuture: CordaFuture<out NodeHandle>) = handleFuture.getOrThrow().apply {
|
||||
@ -32,26 +30,15 @@ class DriverTests {
|
||||
// Check that the port is bound
|
||||
addressMustNotBeBound(executorService, hostAndPort)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `simple node startup and shutdown`() {
|
||||
val handles = driver {
|
||||
val notary = startNotaryNode(DUMMY_NOTARY.name, validating = false)
|
||||
val handle = driver {
|
||||
val regulator = startNode(providedName = DUMMY_REGULATOR.name)
|
||||
listOf(nodeMustBeUp(notary), nodeMustBeUp(regulator))
|
||||
nodeMustBeUp(regulator)
|
||||
}
|
||||
handles.map { nodeMustBeDown(it) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `starting node with no services`() {
|
||||
val noService = driver {
|
||||
val noService = startNode(providedName = DUMMY_BANK_A.name)
|
||||
nodeMustBeUp(noService)
|
||||
}
|
||||
nodeMustBeDown(noService)
|
||||
nodeMustBeDown(handle)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -15,17 +15,11 @@ import net.corda.testing.driver.DriverDSLExposedInterface
|
||||
/**
|
||||
* A simple wrapper for objects provided by the integration test driver DSL. The fields are lazy so
|
||||
* node construction won't start until you access the members. You can get one of these from the
|
||||
* [alice], [bob] and [notaryAliceAndBob] functions.
|
||||
* [alice], [bob] and [aliceAndBob] functions.
|
||||
*/
|
||||
class PredefinedTestNode internal constructor(party: Party, driver: DriverDSLExposedInterface, ifNotaryIsValidating: Boolean?) {
|
||||
class PredefinedTestNode internal constructor(party: Party, driver: DriverDSLExposedInterface) {
|
||||
val rpcUsers = listOf(User("admin", "admin", setOf("ALL"))) // TODO: Randomize?
|
||||
val nodeFuture by lazy {
|
||||
if (ifNotaryIsValidating != null) {
|
||||
driver.startNotaryNode(providedName = party.name, rpcUsers = rpcUsers, validating = ifNotaryIsValidating)
|
||||
} else {
|
||||
driver.startNode(providedName = party.name, rpcUsers = rpcUsers)
|
||||
}
|
||||
}
|
||||
val nodeFuture by lazy { driver.startNode(providedName = party.name, rpcUsers = rpcUsers) }
|
||||
val node by lazy { nodeFuture.get()!! }
|
||||
val rpc by lazy { node.rpcClientToNode() }
|
||||
|
||||
@ -38,28 +32,21 @@ class PredefinedTestNode internal constructor(party: Party, driver: DriverDSLExp
|
||||
* Returns a plain, entirely stock node pre-configured with the [ALICE] identity. Note that a random key will be generated
|
||||
* for it: you won't have [ALICE_KEY].
|
||||
*/
|
||||
fun DriverDSLExposedInterface.alice(): PredefinedTestNode = PredefinedTestNode(ALICE, this, null)
|
||||
fun DriverDSLExposedInterface.alice(): PredefinedTestNode = PredefinedTestNode(ALICE, this)
|
||||
|
||||
/**
|
||||
* Returns a plain, entirely stock node pre-configured with the [BOB] identity. Note that a random key will be generated
|
||||
* for it: you won't have [BOB_KEY].
|
||||
*/
|
||||
fun DriverDSLExposedInterface.bob(): PredefinedTestNode = PredefinedTestNode(BOB, this, null)
|
||||
fun DriverDSLExposedInterface.bob(): PredefinedTestNode = PredefinedTestNode(BOB, this)
|
||||
|
||||
/**
|
||||
* Returns a plain single node notary pre-configured with the [DUMMY_NOTARY] identity. Note that a random key will be generated
|
||||
* for it: you won't have [DUMMY_NOTARY_KEY].
|
||||
* Returns plain, entirely stock nodes pre-configured with the [ALICE] and [BOB] X.500 names in that order. They have been
|
||||
* started up in parallel and are now ready to use.
|
||||
*/
|
||||
fun DriverDSLExposedInterface.notary(): PredefinedTestNode = PredefinedTestNode(DUMMY_NOTARY, this, true)
|
||||
|
||||
/**
|
||||
* Returns plain, entirely stock nodes pre-configured with the [ALICE], [BOB] and [DUMMY_NOTARY] X.500 names in that
|
||||
* order. They have been started up in parallel and are now ready to use.
|
||||
*/
|
||||
fun DriverDSLExposedInterface.notaryAliceAndBob(): List<PredefinedTestNode> {
|
||||
val notary = notary()
|
||||
fun DriverDSLExposedInterface.aliceAndBob(): List<PredefinedTestNode> {
|
||||
val alice = alice()
|
||||
val bob = bob()
|
||||
listOf(notary.nodeFuture, alice.nodeFuture, bob.nodeFuture).transpose().get()
|
||||
return listOf(alice, bob, notary)
|
||||
listOf(alice.nodeFuture, bob.nodeFuture).transpose().get()
|
||||
return listOf(alice, bob)
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import net.corda.nodeapi.RPCApi
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.nodeapi.internal.serialization.KRYO_RPC_CLIENT_CONTEXT
|
||||
import net.corda.testing.driver.*
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import org.apache.activemq.artemis.api.core.SimpleString
|
||||
import org.apache.activemq.artemis.api.core.TransportConfiguration
|
||||
import org.apache.activemq.artemis.api.core.client.ActiveMQClient
|
||||
@ -230,6 +231,7 @@ fun <A> rpcDriver(
|
||||
initialiseSerialization: Boolean = true,
|
||||
startNodesInProcess: Boolean = false,
|
||||
extraCordappPackagesToScan: List<String> = emptyList(),
|
||||
notarySpecs: List<NotarySpec> = emptyList(),
|
||||
dsl: RPCDriverExposedDSLInterface.() -> A
|
||||
) = genericDriver(
|
||||
driverDsl = RPCDriverDSL(
|
||||
@ -241,7 +243,8 @@ fun <A> rpcDriver(
|
||||
useTestClock = useTestClock,
|
||||
isDebug = isDebug,
|
||||
startNodesInProcess = startNodesInProcess,
|
||||
extraCordappPackagesToScan = extraCordappPackagesToScan
|
||||
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
||||
notarySpecs = notarySpecs
|
||||
)
|
||||
),
|
||||
coerce = { it },
|
||||
|
@ -16,6 +16,7 @@ import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.internal.concurrent.*
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.node.NetworkParameters
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.NotaryInfo
|
||||
import net.corda.core.node.services.NetworkMapCache
|
||||
@ -33,13 +34,12 @@ import net.corda.nodeapi.NodeInfoFilesCopier
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.nodeapi.config.toConfig
|
||||
import net.corda.nodeapi.internal.addShutdownHook
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.common.internal.NetworkParametersCopier
|
||||
import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.initialiseTestSerialization
|
||||
import net.corda.testing.node.ClusterSpec
|
||||
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.slf4j.Logger
|
||||
@ -84,10 +84,48 @@ private val DRIVER_REQUIRED_PERMISSIONS = setOf(
|
||||
invokeRpc(CordaRPCOps::networkMapSnapshot)
|
||||
)
|
||||
|
||||
/**
|
||||
* Object ecapsulating a notary started automatically by the driver.
|
||||
*/
|
||||
data class NotaryHandle(val identity: Party, val validating: Boolean, val nodeHandles: CordaFuture<List<NodeHandle>>)
|
||||
|
||||
/**
|
||||
* This is the interface that's exposed to DSL users.
|
||||
*/
|
||||
interface DriverDSLExposedInterface : CordformContext {
|
||||
/** Returns a list of [NotaryHandle]s matching the list of [NotarySpec]s passed into [driver]. */
|
||||
val notaryHandles: List<NotaryHandle>
|
||||
|
||||
/**
|
||||
* Returns the [NotaryHandle] for the single notary on the network. Throws if there are none or more than one.
|
||||
* @see notaryHandles
|
||||
*/
|
||||
val defaultNotaryHandle: NotaryHandle get() {
|
||||
return when (notaryHandles.size) {
|
||||
0 -> throw IllegalStateException("There are no notaries defined on the network")
|
||||
1 -> notaryHandles[0]
|
||||
else -> throw IllegalStateException("There is more than one notary defined on the network")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identity of the single notary on the network. Throws if there are none or more than one.
|
||||
* @see defaultNotaryHandle
|
||||
*/
|
||||
val defaultNotaryIdentity: Party get() = defaultNotaryHandle.identity
|
||||
|
||||
/**
|
||||
* Returns a [CordaFuture] on the [NodeHandle] for the single-node notary on the network. Throws if there
|
||||
* are no notaries or more than one, or if the notary is a distributed cluster.
|
||||
* @see defaultNotaryHandle
|
||||
* @see notaryHandles
|
||||
*/
|
||||
val defaultNotaryNode: CordaFuture<NodeHandle> get() {
|
||||
return defaultNotaryHandle.nodeHandles.map {
|
||||
it.singleOrNull() ?: throw IllegalStateException("Default notary is not a single node")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a node.
|
||||
*
|
||||
@ -110,13 +148,6 @@ interface DriverDSLExposedInterface : CordformContext {
|
||||
startInSameProcess: Boolean? = defaultParameters.startInSameProcess,
|
||||
maximumHeapSize: String = defaultParameters.maximumHeapSize): CordaFuture<NodeHandle>
|
||||
|
||||
// TODO This method has been added temporarily, to be deleted once the set of notaries is defined at the network level.
|
||||
fun startNotaryNode(providedName: CordaX500Name,
|
||||
rpcUsers: List<User> = emptyList(),
|
||||
verifierType: VerifierType = VerifierType.InMemory,
|
||||
customOverrides: Map<String, Any?> = emptyMap(),
|
||||
validating: Boolean = true): CordaFuture<NodeHandle>
|
||||
|
||||
/**
|
||||
* Helper function for starting a [Node] with custom parameters from Java.
|
||||
*
|
||||
@ -131,24 +162,6 @@ interface DriverDSLExposedInterface : CordformContext {
|
||||
maximumHeapSize: String = "200m"
|
||||
): List<CordaFuture<NodeHandle>>
|
||||
|
||||
/**
|
||||
* Starts a distributed notary cluster.
|
||||
*
|
||||
* @param notaryName The legal name of the advertised distributed notary service.
|
||||
* @param clusterSize Number of nodes to create for the cluster.
|
||||
* @param verifierType The type of transaction verifier to use. See: [VerifierType]
|
||||
* @param rpcUsers List of users who are authorised to use the RPC system. Defaults to empty list.
|
||||
* @param startInSameProcess Determines if the node should be started inside the same process the Driver is running
|
||||
* in. If null the Driver-level value will be used.
|
||||
* @return The [Party] identity of the distributed notary service, and the [NodeInfo]s of the notaries in the cluster.
|
||||
*/
|
||||
fun startNotaryCluster(
|
||||
notaryName: CordaX500Name,
|
||||
clusterSize: Int = 3,
|
||||
verifierType: VerifierType = VerifierType.InMemory,
|
||||
rpcUsers: List<User> = emptyList(),
|
||||
startInSameProcess: Boolean? = null): CordaFuture<Pair<Party, List<NodeHandle>>>
|
||||
|
||||
/** Call [startWebserver] with a default maximumHeapSize. */
|
||||
fun startWebserver(handle: NodeHandle): CordaFuture<WebserverHandle> = startWebserver(handle, "200m")
|
||||
|
||||
@ -310,6 +323,8 @@ data class NodeParameters(
|
||||
* @param useTestClock If true the test clock will be used in Node.
|
||||
* @param startNodesInProcess Provides the default behaviour of whether new nodes should start inside this process or
|
||||
* not. Note that this may be overridden in [DriverDSLExposedInterface.startNode].
|
||||
* @param notarySpecs The notaries advertised in the [NetworkParameters] for this network. These nodes will be started
|
||||
* automatically and will be available from [DriverDSLExposedInterface.notaryHandles]. Defaults to a simple validating notary.
|
||||
* @param dsl The dsl itself.
|
||||
* @return The value returned in the [dsl] closure.
|
||||
*/
|
||||
@ -323,6 +338,7 @@ fun <A> driver(
|
||||
useTestClock: Boolean = defaultParameters.useTestClock,
|
||||
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
|
||||
startNodesInProcess: Boolean = defaultParameters.startNodesInProcess,
|
||||
notarySpecs: List<NotarySpec> = defaultParameters.notarySpecs,
|
||||
extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan,
|
||||
dsl: DriverDSLExposedInterface.() -> A
|
||||
): A {
|
||||
@ -335,6 +351,7 @@ fun <A> driver(
|
||||
useTestClock = useTestClock,
|
||||
isDebug = isDebug,
|
||||
startNodesInProcess = startNodesInProcess,
|
||||
notarySpecs = notarySpecs,
|
||||
extraCordappPackagesToScan = extraCordappPackagesToScan
|
||||
),
|
||||
coerce = { it },
|
||||
@ -368,6 +385,7 @@ data class DriverParameters(
|
||||
val useTestClock: Boolean = false,
|
||||
val initialiseSerialization: Boolean = true,
|
||||
val startNodesInProcess: Boolean = false,
|
||||
val notarySpecs: List<NotarySpec> = listOf(NotarySpec(DUMMY_NOTARY.name)),
|
||||
val extraCordappPackagesToScan: List<String> = emptyList()
|
||||
) {
|
||||
fun setIsDebug(isDebug: Boolean) = copy(isDebug = isDebug)
|
||||
@ -379,6 +397,7 @@ data class DriverParameters(
|
||||
fun setInitialiseSerialization(initialiseSerialization: Boolean) = copy(initialiseSerialization = initialiseSerialization)
|
||||
fun setStartNodesInProcess(startNodesInProcess: Boolean) = copy(startNodesInProcess = startNodesInProcess)
|
||||
fun setExtraCordappPackagesToScan(extraCordappPackagesToScan: List<String>) = copy(extraCordappPackagesToScan = extraCordappPackagesToScan)
|
||||
fun setNotarySpecs(notarySpecs: List<NotarySpec>) = copy(notarySpecs = notarySpecs)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -428,10 +447,10 @@ fun <DI : DriverDSLExposedInterface, D : DriverDSLInternalInterface, A> genericD
|
||||
useTestClock: Boolean = defaultParameters.useTestClock,
|
||||
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
|
||||
startNodesInProcess: Boolean = defaultParameters.startNodesInProcess,
|
||||
notarySpecs: List<NotarySpec>,
|
||||
extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan,
|
||||
driverDslWrapper: (DriverDSL) -> D,
|
||||
coerce: (D) -> DI,
|
||||
dsl: DI.() -> A
|
||||
coerce: (D) -> DI, dsl: DI.() -> A
|
||||
): A {
|
||||
val serializationEnv = initialiseTestSerialization(initialiseSerialization)
|
||||
val driverDsl = driverDslWrapper(
|
||||
@ -443,7 +462,8 @@ fun <DI : DriverDSLExposedInterface, D : DriverDSLInternalInterface, A> genericD
|
||||
useTestClock = useTestClock,
|
||||
isDebug = isDebug,
|
||||
startNodesInProcess = startNodesInProcess,
|
||||
extraCordappPackagesToScan = extraCordappPackagesToScan
|
||||
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
||||
notarySpecs = notarySpecs
|
||||
)
|
||||
)
|
||||
val shutdownHook = addShutdownHook(driverDsl::shutdown)
|
||||
@ -643,7 +663,8 @@ class DriverDSL(
|
||||
val useTestClock: Boolean,
|
||||
val isDebug: Boolean,
|
||||
val startNodesInProcess: Boolean,
|
||||
extraCordappPackagesToScan: List<String>
|
||||
extraCordappPackagesToScan: List<String>,
|
||||
val notarySpecs: List<NotarySpec>
|
||||
) : DriverDSLInternalInterface {
|
||||
private var _executorService: ScheduledExecutorService? = null
|
||||
val executorService get() = _executorService!!
|
||||
@ -656,7 +677,9 @@ class DriverDSL(
|
||||
private val nodeInfoFilesCopier = NodeInfoFilesCopier()
|
||||
// Map from a nodes legal name to an observable emitting the number of nodes in its network map.
|
||||
private val countObservables = mutableMapOf<CordaX500Name, Observable<Int>>()
|
||||
private var networkParameters: NetworkParametersCopier? = null
|
||||
private lateinit var _notaries: List<NotaryHandle>
|
||||
override val notaryHandles: List<NotaryHandle> get() = _notaries
|
||||
private lateinit var networkParameters: NetworkParametersCopier
|
||||
|
||||
class State {
|
||||
val processes = ArrayList<CordaFuture<Process>>()
|
||||
@ -744,16 +767,6 @@ class DriverDSL(
|
||||
return startNodeInternal(config, webAddress, startInSameProcess, maximumHeapSize)
|
||||
}
|
||||
|
||||
override fun startNotaryNode(providedName: CordaX500Name,
|
||||
rpcUsers: List<User>,
|
||||
verifierType: VerifierType,
|
||||
customOverrides: Map<String, Any?>,
|
||||
validating: Boolean): CordaFuture<NodeHandle> {
|
||||
createNetworkParameters(listOf(providedName), providedName, validating, "identity")
|
||||
val config = customOverrides + NotaryConfig(validating).toConfigMap()
|
||||
return startNode(providedName = providedName, rpcUsers = rpcUsers, verifierType = verifierType, customOverrides = config)
|
||||
}
|
||||
|
||||
override fun startNodes(nodes: List<CordformNode>, startInSameProcess: Boolean?, maximumHeapSize: String): List<CordaFuture<NodeHandle>> {
|
||||
return nodes.map { node ->
|
||||
portAllocation.nextHostAndPort() // rpcAddress
|
||||
@ -772,72 +785,6 @@ class DriverDSL(
|
||||
}
|
||||
}
|
||||
|
||||
// TODO This mapping is done is several plaecs including the gradle plugin. In general we need a better way of
|
||||
// generating the configs for the nodes, probably making use of Any.toConfig()
|
||||
private fun NotaryConfig.toConfigMap(): Map<String, Any> = mapOf("notary" to toConfig().root().unwrapped())
|
||||
|
||||
override fun startNotaryCluster(
|
||||
notaryName: CordaX500Name,
|
||||
clusterSize: Int,
|
||||
verifierType: VerifierType,
|
||||
rpcUsers: List<User>,
|
||||
startInSameProcess: Boolean?
|
||||
): CordaFuture<Pair<Party, List<NodeHandle>>> {
|
||||
fun notaryConfig(nodeAddress: NetworkHostAndPort, clusterAddress: NetworkHostAndPort? = null): Map<String, Any> {
|
||||
val clusterAddresses = if (clusterAddress != null) listOf(clusterAddress) else emptyList()
|
||||
val config = NotaryConfig(validating = true, raft = RaftConfig(nodeAddress = nodeAddress, clusterAddresses = clusterAddresses))
|
||||
return config.toConfigMap()
|
||||
}
|
||||
|
||||
require(clusterSize > 0)
|
||||
|
||||
val nodeNames = (0 until clusterSize).map { notaryName.copy(organisation = "${notaryName.organisation}-$it") }
|
||||
val notaryIdentity = createNetworkParameters(
|
||||
nodeNames,
|
||||
notaryName,
|
||||
validating = true,
|
||||
serviceId = NotaryService.constructId(validating = true, raft = true))
|
||||
|
||||
val clusterAddress = portAllocation.nextHostAndPort()
|
||||
|
||||
// Start the first node that will bootstrap the cluster
|
||||
val firstNotaryFuture = startNode(
|
||||
providedName = nodeNames[0],
|
||||
rpcUsers = rpcUsers,
|
||||
verifierType = verifierType,
|
||||
customOverrides = notaryConfig(clusterAddress) + mapOf(
|
||||
"database.serverNameTablePrefix" to nodeNames[0].toString().replace(Regex("[^0-9A-Za-z]+"), "")
|
||||
),
|
||||
startInSameProcess = startInSameProcess
|
||||
)
|
||||
|
||||
// All other nodes will join the cluster
|
||||
val restNotaryFutures = nodeNames.drop(1).map {
|
||||
val nodeAddress = portAllocation.nextHostAndPort()
|
||||
startNode(
|
||||
providedName = it,
|
||||
rpcUsers = rpcUsers,
|
||||
verifierType = verifierType,
|
||||
customOverrides = notaryConfig(nodeAddress, clusterAddress) + mapOf(
|
||||
"database.serverNameTablePrefix" to it.toString().replace(Regex("[^0-9A-Za-z]+"), "")
|
||||
))
|
||||
}
|
||||
|
||||
return firstNotaryFuture.flatMap { firstNotary ->
|
||||
restNotaryFutures.transpose().map { restNotaries -> Pair(notaryIdentity, listOf(firstNotary) + restNotaries) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun createNetworkParameters(notaryNodeNames: List<CordaX500Name>, notaryName: CordaX500Name, validating: Boolean, serviceId: String): Party {
|
||||
check(networkParameters == null) { "Notaries must be started first" }
|
||||
val identity = ServiceIdentityGenerator.generateToDisk(
|
||||
notaryNodeNames.map { baseDirectory(it) },
|
||||
notaryName,
|
||||
serviceId)
|
||||
networkParameters = NetworkParametersCopier(testNetworkParameters(listOf(NotaryInfo(identity, validating))))
|
||||
return identity
|
||||
}
|
||||
|
||||
private fun queryWebserver(handle: NodeHandle, process: Process): WebserverHandle {
|
||||
val protocol = if (handle.configuration.useHTTPS) "https://" else "http://"
|
||||
val url = URL("$protocol${handle.webAddress}/api/status")
|
||||
@ -866,6 +813,97 @@ class DriverDSL(
|
||||
_executorService = Executors.newScheduledThreadPool(2, ThreadFactoryBuilder().setNameFormat("driver-pool-thread-%d").build())
|
||||
_shutdownManager = ShutdownManager(executorService)
|
||||
shutdownManager.registerShutdown { nodeInfoFilesCopier.close() }
|
||||
val notaryInfos = generateNotaryIdentities()
|
||||
// The network parameters must be serialised before starting any of the nodes
|
||||
networkParameters = NetworkParametersCopier(testNetworkParameters(notaryInfos))
|
||||
val nodeHandles = startNotaries()
|
||||
_notaries = notaryInfos.zip(nodeHandles) { (identity, validating), nodes -> NotaryHandle(identity, validating, nodes) }
|
||||
}
|
||||
|
||||
private fun generateNotaryIdentities(): List<NotaryInfo> {
|
||||
return notarySpecs.map { spec ->
|
||||
val identity = if (spec.cluster == null) {
|
||||
ServiceIdentityGenerator.generateToDisk(
|
||||
dirs = listOf(baseDirectory(spec.name)),
|
||||
serviceName = spec.name,
|
||||
serviceId = "identity")
|
||||
} else {
|
||||
ServiceIdentityGenerator.generateToDisk(
|
||||
dirs = generateNodeNames(spec).map { baseDirectory(it) },
|
||||
serviceName = spec.name,
|
||||
serviceId = NotaryService.constructId(
|
||||
validating = spec.validating,
|
||||
raft = spec.cluster is ClusterSpec.Raft))
|
||||
}
|
||||
NotaryInfo(identity, spec.validating)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateNodeNames(spec: NotarySpec): List<CordaX500Name> {
|
||||
return (0 until spec.cluster!!.clusterSize).map { spec.name.copy(organisation = "${spec.name.organisation}-$it") }
|
||||
}
|
||||
|
||||
private fun startNotaries(): List<CordaFuture<List<NodeHandle>>> {
|
||||
return notarySpecs.map {
|
||||
when {
|
||||
it.cluster == null -> startSingleNotary(it)
|
||||
it.cluster is ClusterSpec.Raft -> startRaftNotaryCluster(it)
|
||||
else -> throw IllegalArgumentException("BFT-SMaRt not supported")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO This mapping is done is several places including the gradle plugin. In general we need a better way of
|
||||
// generating the configs for the nodes, probably making use of Any.toConfig()
|
||||
private fun NotaryConfig.toConfigMap(): Map<String, Any> = mapOf("notary" to toConfig().root().unwrapped())
|
||||
|
||||
private fun startSingleNotary(spec: NotarySpec): CordaFuture<List<NodeHandle>> {
|
||||
return startNode(
|
||||
providedName = spec.name,
|
||||
rpcUsers = spec.rpcUsers,
|
||||
verifierType = spec.verifierType,
|
||||
customOverrides = NotaryConfig(spec.validating).toConfigMap()
|
||||
).map { listOf(it) }
|
||||
}
|
||||
|
||||
private fun startRaftNotaryCluster(spec: NotarySpec): CordaFuture<List<NodeHandle>> {
|
||||
fun notaryConfig(nodeAddress: NetworkHostAndPort, clusterAddress: NetworkHostAndPort? = null): Map<String, Any> {
|
||||
val clusterAddresses = if (clusterAddress != null) listOf(clusterAddress) else emptyList()
|
||||
val config = NotaryConfig(
|
||||
validating = spec.validating,
|
||||
raft = RaftConfig(nodeAddress = nodeAddress, clusterAddresses = clusterAddresses))
|
||||
return config.toConfigMap()
|
||||
}
|
||||
|
||||
val nodeNames = generateNodeNames(spec)
|
||||
val clusterAddress = portAllocation.nextHostAndPort()
|
||||
|
||||
// Start the first node that will bootstrap the cluster
|
||||
val firstNodeFuture = startNode(
|
||||
providedName = nodeNames[0],
|
||||
rpcUsers = spec.rpcUsers,
|
||||
verifierType = spec.verifierType,
|
||||
customOverrides = notaryConfig(clusterAddress) + mapOf(
|
||||
"database.serverNameTablePrefix" to nodeNames[0].toString().replace(Regex("[^0-9A-Za-z]+"), "")
|
||||
)
|
||||
)
|
||||
|
||||
// All other nodes will join the cluster
|
||||
val restNodeFutures = nodeNames.drop(1).map {
|
||||
val nodeAddress = portAllocation.nextHostAndPort()
|
||||
startNode(
|
||||
providedName = it,
|
||||
rpcUsers = spec.rpcUsers,
|
||||
verifierType = spec.verifierType,
|
||||
customOverrides = notaryConfig(nodeAddress, clusterAddress) + mapOf(
|
||||
"database.serverNameTablePrefix" to it.toString().replace(Regex("[^0-9A-Za-z]+"), "")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return firstNodeFuture.flatMap { first ->
|
||||
restNodeFutures.transpose().map { rest -> listOf(first) + rest }
|
||||
}
|
||||
}
|
||||
|
||||
fun baseDirectory(nodeName: CordaX500Name): Path {
|
||||
@ -925,10 +963,7 @@ class DriverDSL(
|
||||
maximumHeapSize: String): CordaFuture<NodeHandle> {
|
||||
val configuration = config.parseAsNodeConfiguration()
|
||||
val baseDirectory = configuration.baseDirectory.createDirectories()
|
||||
if (networkParameters == null) {
|
||||
networkParameters = NetworkParametersCopier(testNetworkParameters(emptyList()))
|
||||
}
|
||||
networkParameters!!.install(baseDirectory)
|
||||
networkParameters.install(baseDirectory)
|
||||
nodeInfoFilesCopier.addConfig(baseDirectory)
|
||||
val onNodeExit: () -> Unit = {
|
||||
nodeInfoFilesCopier.removeConfig(baseDirectory)
|
||||
|
@ -7,6 +7,7 @@ import com.nhaarman.mockito_kotlin.whenever
|
||||
import net.corda.core.crypto.entropyToKeyPair
|
||||
import net.corda.core.crypto.random63BitValue
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.createDirectories
|
||||
import net.corda.core.internal.createDirectory
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
@ -110,6 +111,9 @@ data class MockNodeArgs(
|
||||
* You can get a printout of every message sent by using code like:
|
||||
*
|
||||
* LogHelper.setLevel("+messages")
|
||||
*
|
||||
* By default a single notary node is automatically started, which forms part of the network parameters for all the nodes.
|
||||
* This node is available by calling [defaultNotaryNode].
|
||||
*/
|
||||
class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParameters(),
|
||||
private val networkSendManuallyPumped: Boolean = defaultParameters.networkSendManuallyPumped,
|
||||
@ -117,6 +121,7 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
|
||||
servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = defaultParameters.servicePeerAllocationStrategy,
|
||||
private val defaultFactory: (MockNodeArgs) -> MockNode = defaultParameters.defaultFactory,
|
||||
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
|
||||
private val notarySpecs: List<NotarySpec> = listOf(NotarySpec(DUMMY_NOTARY.name)),
|
||||
private val cordappPackages: List<String> = defaultParameters.cordappPackages) : Closeable {
|
||||
/** Helper constructor for creating a [MockNetwork] with custom parameters from Java. */
|
||||
constructor(parameters: MockNetworkParameters) : this(defaultParameters = parameters)
|
||||
@ -128,22 +133,43 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
|
||||
val messagingNetwork = InMemoryMessagingNetwork(networkSendManuallyPumped, servicePeerAllocationStrategy, busyLatch)
|
||||
// A unique identifier for this network to segregate databases with the same nodeID but different networks.
|
||||
private val networkId = random63BitValue()
|
||||
private lateinit var networkParameters: NetworkParametersCopier
|
||||
private var notaryInfos: MutableList<NotaryInfo>? = ArrayList()
|
||||
private val _nodes = ArrayList<MockNode>()
|
||||
private val networkParameters: NetworkParametersCopier
|
||||
private val _nodes = mutableListOf<MockNode>()
|
||||
private val serializationEnv = initialiseTestSerialization(initialiseSerialization)
|
||||
private val sharedUserCount = AtomicInteger(0)
|
||||
|
||||
/** A read only view of the current set of executing nodes. */
|
||||
val nodes: List<MockNode> get() = _nodes
|
||||
|
||||
init {
|
||||
filesystem.getPath("/nodes").createDirectory()
|
||||
/**
|
||||
* Returns the list of nodes started by the network. Each notary specified when the network is constructed ([notarySpecs]
|
||||
* parameter) maps 1:1 to the notaries returned by this list.
|
||||
*/
|
||||
val notaryNodes: List<StartedNode<MockNode>>
|
||||
|
||||
/**
|
||||
* Returns the single notary node on the network. Throws if there are none or more than one.
|
||||
* @see notaryNodes
|
||||
*/
|
||||
val defaultNotaryNode: StartedNode<MockNode> get() {
|
||||
return when (notaryNodes.size) {
|
||||
0 -> throw IllegalStateException("There are no notaries defined on the network")
|
||||
1 -> notaryNodes[0]
|
||||
else -> throw IllegalStateException("There is more than one notary defined on the network")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the identity of the default notary node.
|
||||
* @see defaultNotaryNode
|
||||
*/
|
||||
val defaultNotaryIdentity: Party get() {
|
||||
return defaultNotaryNode.info.legalIdentities.singleOrNull() ?: throw IllegalStateException("Default notary has multiple identities")
|
||||
}
|
||||
|
||||
/**
|
||||
* Because this executor is shared, we need to be careful about nodes shutting it down.
|
||||
*/
|
||||
private val sharedUserCount = AtomicInteger(0)
|
||||
private val sharedServerThread = object : ServiceAffinityExecutor("Mock network", 1) {
|
||||
override fun shutdown() {
|
||||
// We don't actually allow the shutdown of the network-wide shared thread pool until all references to
|
||||
@ -163,6 +189,32 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
filesystem.getPath("/nodes").createDirectory()
|
||||
val notaryInfos = generateNotaryIdentities()
|
||||
// The network parameters must be serialised before starting any of the nodes
|
||||
networkParameters = NetworkParametersCopier(testNetworkParameters(notaryInfos))
|
||||
notaryNodes = createNotaries()
|
||||
}
|
||||
|
||||
private fun generateNotaryIdentities(): List<NotaryInfo> {
|
||||
return notarySpecs.mapIndexed { index, spec ->
|
||||
val identity = ServiceIdentityGenerator.generateToDisk(
|
||||
dirs = listOf(baseDirectory(nextNodeId + index)),
|
||||
serviceName = spec.name,
|
||||
serviceId = "identity")
|
||||
NotaryInfo(identity, spec.validating)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createNotaries(): List<StartedNode<MockNode>> {
|
||||
return notarySpecs.map { spec ->
|
||||
createNode(MockNodeParameters(legalName = spec.name, configOverrides = {
|
||||
doReturn(NotaryConfig(spec.validating)).whenever(it).notary
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
open class MockNode(args: MockNodeArgs) : AbstractNode(
|
||||
args.config,
|
||||
TestClock(),
|
||||
@ -188,20 +240,12 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
|
||||
override val started: StartedNode<MockNode>? get() = uncheckedCast(super.started)
|
||||
|
||||
override fun start(): StartedNode<MockNode> {
|
||||
installNetworkParameters()
|
||||
mockNet.networkParameters.install(configuration.baseDirectory)
|
||||
val started: StartedNode<MockNode> = uncheckedCast(super.start())
|
||||
advertiseNodeToNetwork(started)
|
||||
return started
|
||||
}
|
||||
|
||||
private fun installNetworkParameters() {
|
||||
mockNet.notaryInfos?.let {
|
||||
mockNet.networkParameters = NetworkParametersCopier(testNetworkParameters(it))
|
||||
}
|
||||
mockNet.notaryInfos = null
|
||||
mockNet.networkParameters.install(configuration.baseDirectory)
|
||||
}
|
||||
|
||||
private fun advertiseNodeToNetwork(newNode: StartedNode<MockNode>) {
|
||||
mockNet.nodes
|
||||
.mapNotNull { it.started }
|
||||
@ -273,9 +317,6 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
|
||||
dbCloser = null
|
||||
}
|
||||
|
||||
fun hasDBConnection() = dbCloser != null
|
||||
|
||||
// You can change this from zero if you have custom [FlowLogic] that park themselves. e.g. [StateMachineManagerTests]
|
||||
var acceptableLiveFiberCountOnStop: Int = 0
|
||||
|
||||
override fun acceptableLiveFiberCountOnStop(): Int = acceptableLiveFiberCountOnStop
|
||||
@ -321,23 +362,11 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
|
||||
doReturn(makeTestDataSourceProperties("node_${id}_net_$networkId")).whenever(it).dataSourceProperties
|
||||
parameters.configOverrides(it)
|
||||
}
|
||||
|
||||
val node = nodeFactory(MockNodeArgs(config, this, id, parameters.entropyRoot))
|
||||
_nodes += node
|
||||
|
||||
config.notary?.let { notaryConfig ->
|
||||
val notaryInfos = notaryInfos ?: throw IllegalStateException("Cannot add notaries once nodes have started")
|
||||
if (!notaryConfig.isClusterConfig) {
|
||||
// Create the node's main identity, which will also double as its notary identity
|
||||
val identity = ServiceIdentityGenerator.generateToDisk(listOf(config.baseDirectory), config.myLegalName, "identity")
|
||||
notaryInfos += NotaryInfo(identity, notaryConfig.validating)
|
||||
}
|
||||
}
|
||||
|
||||
if (start) {
|
||||
node.start()
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
@ -365,24 +394,7 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun createNotaryNode(parameters: MockNodeParameters = MockNodeParameters(legalName = DUMMY_NOTARY.name),
|
||||
validating: Boolean = true): StartedNode<MockNode> {
|
||||
return createNotaryNode(parameters, validating, defaultFactory)
|
||||
}
|
||||
|
||||
fun <N : MockNode> createNotaryNode(parameters: MockNodeParameters = MockNodeParameters(legalName = DUMMY_NOTARY.name),
|
||||
validating: Boolean = true,
|
||||
nodeFactory: (MockNodeArgs) -> N): StartedNode<N> {
|
||||
return createNode(
|
||||
parameters.copy(configOverrides = {
|
||||
doReturn(NotaryConfig(validating)).whenever(it).notary
|
||||
parameters.configOverrides(it)
|
||||
}),
|
||||
nodeFactory
|
||||
)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun createPartyNode(legalName: CordaX500Name? = null): StartedNode<MockNode> {
|
||||
return createNode(MockNodeParameters(legalName = legalName))
|
||||
}
|
||||
@ -418,14 +430,16 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
|
||||
override fun close() {
|
||||
stopNodes()
|
||||
}
|
||||
|
||||
data class NotarySpec(val name: CordaX500Name, val validating: Boolean = true) {
|
||||
constructor(name: CordaX500Name) : this(name, validating = true)
|
||||
}
|
||||
}
|
||||
|
||||
fun network(nodesCount: Int, action: MockNetwork.(nodes: List<StartedNode<MockNetwork.MockNode>>, notary: StartedNode<MockNetwork.MockNode>) -> Unit) {
|
||||
MockNetwork().use {
|
||||
it.runNetwork()
|
||||
val notary = it.createNotaryNode()
|
||||
val nodes = (1..nodesCount).map { _ -> it.createPartyNode() }
|
||||
action(it, nodes, notary)
|
||||
fun network(nodesCount: Int, action: MockNetwork.(List<StartedNode<MockNetwork.MockNode>>) -> Unit) {
|
||||
MockNetwork().use { mockNet ->
|
||||
val nodes = (1..nodesCount).map { mockNet.createPartyNode() }
|
||||
mockNet.action(nodes)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
package net.corda.testing.node
|
||||
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.node.services.config.VerifierType
|
||||
import net.corda.nodeapi.User
|
||||
|
||||
data class NotarySpec(
|
||||
val name: CordaX500Name,
|
||||
val validating: Boolean = true,
|
||||
val rpcUsers: List<User> = emptyList(),
|
||||
val verifierType: VerifierType = VerifierType.InMemory,
|
||||
val cluster: ClusterSpec? = null
|
||||
)
|
||||
|
||||
sealed class ClusterSpec {
|
||||
abstract val clusterSize: Int
|
||||
|
||||
data class Raft(override val clusterSize: Int) : ClusterSpec() {
|
||||
init {
|
||||
require(clusterSize > 0)
|
||||
}
|
||||
}
|
||||
}
|
@ -24,14 +24,13 @@ import net.corda.node.services.Permissions.Companion.startFlow
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.driver.NodeHandle
|
||||
import net.corda.testing.driver.PortAllocation
|
||||
import net.corda.testing.driver.driver
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
|
||||
class ExplorerSimulation(val options: OptionSet) {
|
||||
class ExplorerSimulation(private val options: OptionSet) {
|
||||
private val user = User("user1", "test", permissions = setOf(
|
||||
startFlow<CashPaymentFlow>(),
|
||||
startFlow<CashConfigDataFlow>()
|
||||
@ -67,23 +66,16 @@ class ExplorerSimulation(val options: OptionSet) {
|
||||
val portAllocation = PortAllocation.Incremental(20000)
|
||||
driver(portAllocation = portAllocation, extraCordappPackagesToScan = listOf("net.corda.finance")) {
|
||||
// TODO : Supported flow should be exposed somehow from the node instead of set of ServiceInfo.
|
||||
val notary = startNotaryNode(DUMMY_NOTARY.name, customOverrides = mapOf("nearestCity" to "Zurich"), validating = false)
|
||||
val alice = startNode(providedName = ALICE.name, rpcUsers = arrayListOf(user),
|
||||
customOverrides = mapOf("nearestCity" to "Milan"))
|
||||
val bob = startNode(providedName = BOB.name, rpcUsers = arrayListOf(user),
|
||||
customOverrides = mapOf("nearestCity" to "Madrid"))
|
||||
val alice = startNode(providedName = ALICE.name, rpcUsers = listOf(user))
|
||||
val bob = startNode(providedName = BOB.name, rpcUsers = listOf(user))
|
||||
val ukBankName = CordaX500Name(organisation = "UK Bank Plc", locality = "London", country = "GB")
|
||||
val usaBankName = CordaX500Name(organisation = "USA Bank Corp", locality = "New York", country = "US")
|
||||
val issuerGBP = startNode(providedName = ukBankName, rpcUsers = arrayListOf(manager),
|
||||
customOverrides = mapOf(
|
||||
"issuableCurrencies" to listOf("GBP"),
|
||||
"nearestCity" to "London"))
|
||||
val issuerUSD = startNode(providedName = usaBankName, rpcUsers = arrayListOf(manager),
|
||||
customOverrides = mapOf(
|
||||
"issuableCurrencies" to listOf("USD"),
|
||||
"nearestCity" to "New York"))
|
||||
val issuerGBP = startNode(providedName = ukBankName, rpcUsers = listOf(manager),
|
||||
customOverrides = mapOf("issuableCurrencies" to listOf("GBP")))
|
||||
val issuerUSD = startNode(providedName = usaBankName, rpcUsers = listOf(manager),
|
||||
customOverrides = mapOf("issuableCurrencies" to listOf("USD")))
|
||||
|
||||
notaryNode = notary.get()
|
||||
notaryNode = defaultNotaryNode.get()
|
||||
aliceNode = alice.get()
|
||||
bobNode = bob.get()
|
||||
issuerNodeGBP = issuerGBP.get()
|
||||
|
@ -19,6 +19,7 @@ import net.corda.nodeapi.VerifierApi
|
||||
import net.corda.nodeapi.config.NodeSSLConfiguration
|
||||
import net.corda.nodeapi.config.SSLConfiguration
|
||||
import net.corda.testing.driver.*
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import org.apache.activemq.artemis.api.core.SimpleString
|
||||
import org.apache.activemq.artemis.api.core.client.ActiveMQClient
|
||||
import org.apache.activemq.artemis.api.core.client.ClientProducer
|
||||
@ -77,6 +78,7 @@ fun <A> verifierDriver(
|
||||
useTestClock: Boolean = false,
|
||||
startNodesInProcess: Boolean = false,
|
||||
extraCordappPackagesToScan: List<String> = emptyList(),
|
||||
notarySpecs: List<NotarySpec> = emptyList(),
|
||||
dsl: VerifierExposedDSLInterface.() -> A
|
||||
) = genericDriver(
|
||||
driverDsl = VerifierDriverDSL(
|
||||
@ -88,7 +90,8 @@ fun <A> verifierDriver(
|
||||
useTestClock = useTestClock,
|
||||
isDebug = isDebug,
|
||||
startNodesInProcess = startNodesInProcess,
|
||||
extraCordappPackagesToScan = extraCordappPackagesToScan
|
||||
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
||||
notarySpecs = notarySpecs
|
||||
)
|
||||
),
|
||||
coerce = { it },
|
||||
|
@ -15,6 +15,7 @@ import net.corda.node.services.config.VerifierType
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.ALICE_NAME
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import org.junit.Test
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
@ -128,15 +129,15 @@ class VerifierTests {
|
||||
|
||||
@Test
|
||||
fun `single verifier works with a node`() {
|
||||
verifierDriver(extraCordappPackagesToScan = listOf("net.corda.finance.contracts")) {
|
||||
val (notaryNode, aliceNode) = listOf(
|
||||
startNotaryNode(DUMMY_NOTARY.name, verifierType = VerifierType.OutOfProcess),
|
||||
startNode(providedName = ALICE.name)
|
||||
).transpose().getOrThrow()
|
||||
verifierDriver(
|
||||
extraCordappPackagesToScan = listOf("net.corda.finance.contracts"),
|
||||
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name, verifierType = VerifierType.OutOfProcess))
|
||||
) {
|
||||
val aliceNode = startNode(providedName = ALICE.name).getOrThrow()
|
||||
val notaryNode = defaultNotaryNode.getOrThrow()
|
||||
val alice = aliceNode.rpc.wellKnownPartyFromX500Name(ALICE_NAME)!!
|
||||
val notary = notaryNode.rpc.notaryPartyFromX500Name(DUMMY_NOTARY.name)!!
|
||||
startVerifier(notaryNode)
|
||||
aliceNode.rpc.startFlow(::CashIssueFlow, 10.DOLLARS, OpaqueBytes.of(0), notary).returnValue.get()
|
||||
aliceNode.rpc.startFlow(::CashIssueFlow, 10.DOLLARS, OpaqueBytes.of(0), defaultNotaryIdentity).returnValue.get()
|
||||
notaryNode.waitUntilNumberOfVerifiers(1)
|
||||
for (i in 1..10) {
|
||||
val cashFlowResult = aliceNode.rpc.startFlow(::CashPaymentFlow, 10.DOLLARS, alice).returnValue.get()
|
||||
|
@ -11,7 +11,7 @@ import org.junit.Test
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.ScheduledExecutorService
|
||||
|
||||
class DriverTests {
|
||||
class WebserverDriverTests {
|
||||
companion object {
|
||||
val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user