From f19564f9f8654cae812ae1ebf895671576148ce6 Mon Sep 17 00:00:00 2001 From: Stefano Franz Date: Wed, 4 Jul 2018 11:33:21 +0100 Subject: [PATCH] add simple network verification cordapp (#3412) * add simple network verification cordapp * add ability to filter checked counterparties to specific x500 --- samples/network-verifier/build.gradle | 49 +++++++++++ .../net/corda/verification/TestCommsFlow.kt | 81 +++++++++++++++++++ .../net/corda/verification/TestNotaryFlow.kt | 65 +++++++++++++++ .../TestCommsFlowInitiatorTest.kt | 34 ++++++++ settings.gradle | 1 + 5 files changed, 230 insertions(+) create mode 100644 samples/network-verifier/build.gradle create mode 100644 samples/network-verifier/src/main/kotlin/net/corda/verification/TestCommsFlow.kt create mode 100644 samples/network-verifier/src/main/kotlin/net/corda/verification/TestNotaryFlow.kt create mode 100644 samples/network-verifier/src/test/kotlin/net/corda/configsample/TestCommsFlowInitiatorTest.kt diff --git a/samples/network-verifier/build.gradle b/samples/network-verifier/build.gradle new file mode 100644 index 0000000000..f64efcc692 --- /dev/null +++ b/samples/network-verifier/build.gradle @@ -0,0 +1,49 @@ +apply plugin: 'kotlin' +apply plugin: 'java' +apply plugin: 'net.corda.plugins.cordapp' +apply plugin: 'net.corda.plugins.cordformation' + +dependencies { + cordaCompile project(":core") + cordaCompile project(":node-api") + cordaCompile project(path: ":node:capsule", configuration: 'runtimeArtifacts') + + testCompile project(":test-utils") + testCompile "junit:junit:$junit_version" +} + +task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) { + ext.rpcUsers = [['username': "default", 'password': "default", 'permissions': [ 'ALL' ]]] + + directory "./build/nodes" + node { + name "O=Notary Service,L=Zurich,C=CH" + notary = [validating : false] + p2pPort 10002 + rpcSettings { + port 10003 + adminPort 10004 + } + h2Port 20004 + } + node { + name "O=Bank A,L=London,C=GB" + p2pPort 10005 + cordapps = [] + rpcUsers = ext.rpcUsers + rpcSettings { + port 10007 + adminPort 10008 + } + } + node { + name "O=Bank B,L=New York,C=US" + p2pPort 10009 + cordapps = [] + rpcUsers = ext.rpcUsers + rpcSettings { + port 10011 + adminPort 10012 + } + } +} \ No newline at end of file diff --git a/samples/network-verifier/src/main/kotlin/net/corda/verification/TestCommsFlow.kt b/samples/network-verifier/src/main/kotlin/net/corda/verification/TestCommsFlow.kt new file mode 100644 index 0000000000..3437cce254 --- /dev/null +++ b/samples/network-verifier/src/main/kotlin/net/corda/verification/TestCommsFlow.kt @@ -0,0 +1,81 @@ +package net.corda.verification + +import co.paralleluniverse.fibers.Suspendable +import net.corda.core.contracts.CommandData +import net.corda.core.contracts.Contract +import net.corda.core.contracts.ContractState +import net.corda.core.flows.* +import net.corda.core.identity.AbstractParty +import net.corda.core.identity.CordaX500Name +import net.corda.core.identity.Party +import net.corda.core.serialization.CordaSerializable +import net.corda.core.transactions.LedgerTransaction +import net.corda.core.transactions.TransactionBuilder +import net.corda.core.utilities.ProgressTracker +import net.corda.core.utilities.unwrap + + +@StartableByRPC +@InitiatingFlow +class TestCommsFlowInitiator(val x500Name: CordaX500Name? = null) : FlowLogic>() { + + object SENDING : ProgressTracker.Step("SENDING") + object RECIEVED_ALL : ProgressTracker.Step("RECIEVED_ALL") + object FINALIZING : ProgressTracker.Step("FINALIZING") + + override val progressTracker: ProgressTracker = ProgressTracker(SENDING, RECIEVED_ALL, FINALIZING) + + @Suspendable + override fun call(): List { + progressTracker.currentStep = SENDING + val responses = serviceHub.networkMapCache.allNodes.map { + it.legalIdentities.first() + }.filterNot { + it in serviceHub.myInfo.legalIdentities + }.filterNot { + it in serviceHub.networkMapCache.notaryIdentities + }.filter(::matchesX500) + .map { + val initiateFlow = initiateFlow(it) + initiateFlow.receive().unwrap { it } + }.toList().also { + progressTracker.currentStep = RECIEVED_ALL + } + val tx = TransactionBuilder(notary = serviceHub.networkMapCache.notaryIdentities.first()) + tx.addOutputState(CommsTestState(responses, serviceHub.myInfo.legalIdentities.first()), CommsTestContract::class.qualifiedName!!) + tx.addCommand(CommsTestCommand, serviceHub.myInfo.legalIdentities.first().owningKey) + val signedTx = serviceHub.signInitialTransaction(tx) + subFlow(FinalityFlow(signedTx)) + return responses + } + + fun matchesX500(it: Party): Boolean { + return x500Name?.equals(it.name) ?: true + } +} + +@InitiatedBy(TestCommsFlowInitiator::class) +class TestCommsFlowResponder(val otherSideSession: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + otherSideSession.send("Hello from: " + serviceHub.myInfo.legalIdentities.first().name.toString()) + } + +} + +@CordaSerializable +data class CommsTestState(val responses: List, val issuer: AbstractParty) : ContractState { + override val participants: List + get() = listOf(issuer) + +} + + +@CordaSerializable +object CommsTestCommand : CommandData + + +class CommsTestContract : Contract { + override fun verify(tx: LedgerTransaction) { + } +} \ No newline at end of file diff --git a/samples/network-verifier/src/main/kotlin/net/corda/verification/TestNotaryFlow.kt b/samples/network-verifier/src/main/kotlin/net/corda/verification/TestNotaryFlow.kt new file mode 100644 index 0000000000..91b8d4bbec --- /dev/null +++ b/samples/network-verifier/src/main/kotlin/net/corda/verification/TestNotaryFlow.kt @@ -0,0 +1,65 @@ +package net.corda.verification + +import net.corda.core.contracts.CommandData +import net.corda.core.contracts.Contract +import net.corda.core.contracts.ContractState +import net.corda.core.flows.FinalityFlow +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.StartableByRPC +import net.corda.core.identity.AbstractParty +import net.corda.core.serialization.CordaSerializable +import net.corda.core.transactions.LedgerTransaction +import net.corda.core.transactions.TransactionBuilder +import net.corda.core.utilities.ProgressTracker + + +@StartableByRPC +class TestNotaryFlow : FlowLogic() { + + object ISSUING : ProgressTracker.Step("ISSUING") + object ISSUED : ProgressTracker.Step("ISSUED") + object DESTROYING : ProgressTracker.Step("DESTROYING") + object FINALIZED : ProgressTracker.Step("FINALIZED") + + override val progressTracker: ProgressTracker = ProgressTracker(ISSUING, ISSUED, DESTROYING, FINALIZED) + + + override fun call(): String { + val issueBuilder = TransactionBuilder() + val notary = serviceHub.networkMapCache.notaryIdentities.first() + issueBuilder.notary = notary; + val myIdentity = serviceHub.myInfo.legalIdentities.first() + issueBuilder.addOutputState(NotaryTestState(notary.name.toString(), myIdentity), NotaryTestContract::class.qualifiedName!!) + issueBuilder.addCommand(NotaryTestCommand, myIdentity.owningKey) + val signedTx = serviceHub.signInitialTransaction(issueBuilder) + val issueResult = subFlow(FinalityFlow(signedTx)) + progressTracker.currentStep = ISSUED + val destroyBuilder = TransactionBuilder() + destroyBuilder.notary = notary; + destroyBuilder.addInputState(issueResult.tx.outRefsOfType().first()) + destroyBuilder.addCommand(NotaryTestCommand, myIdentity.owningKey) + val signedDestroyT = serviceHub.signInitialTransaction(destroyBuilder) + val result = subFlow(FinalityFlow(signedDestroyT)) + progressTracker.currentStep = DESTROYING + progressTracker.currentStep = FINALIZED + return "notarised: " + result.notary.toString() + "::" + result.tx.id + } +} + + +@CordaSerializable +data class NotaryTestState(val id: String, val issuer: AbstractParty) : ContractState { + override val participants: List + get() = listOf(issuer) + +} + + +@CordaSerializable +object NotaryTestCommand : CommandData + + +class NotaryTestContract : Contract { + override fun verify(tx: LedgerTransaction) { + } +} \ No newline at end of file diff --git a/samples/network-verifier/src/test/kotlin/net/corda/configsample/TestCommsFlowInitiatorTest.kt b/samples/network-verifier/src/test/kotlin/net/corda/configsample/TestCommsFlowInitiatorTest.kt new file mode 100644 index 0000000000..d0974f0eba --- /dev/null +++ b/samples/network-verifier/src/test/kotlin/net/corda/configsample/TestCommsFlowInitiatorTest.kt @@ -0,0 +1,34 @@ +package net.corda.configsample + +import net.corda.testing.core.ALICE_NAME +import net.corda.testing.core.DUMMY_BANK_A_NAME +import net.corda.testing.core.DUMMY_NOTARY_NAME +import net.corda.testing.core.TestIdentity +import net.corda.verification.TestCommsFlowInitiator +import org.junit.Assert +import org.junit.Test + +class TestCommsFlowInitiatorTest { + + val ALICE = TestIdentity(ALICE_NAME, 70) + val NOTARY = TestIdentity(DUMMY_NOTARY_NAME, 12) + val DUMMY_BANK_A = TestIdentity(DUMMY_BANK_A_NAME, 3) + + @Test + fun `should allow all node infos through if no x500 is passed`() { + val testCommsFlowInitiator = TestCommsFlowInitiator() + + Assert.assertTrue(testCommsFlowInitiator.matchesX500(ALICE.party)) + Assert.assertTrue(testCommsFlowInitiator.matchesX500(NOTARY.party)) + Assert.assertTrue(testCommsFlowInitiator.matchesX500(DUMMY_BANK_A.party)) + } + + @Test + fun `should allow only specified x500 if no x500 is passed`() { + val testCommsFlowInitiator = TestCommsFlowInitiator(ALICE_NAME) + + Assert.assertTrue(testCommsFlowInitiator.matchesX500(ALICE.party)) + Assert.assertFalse(testCommsFlowInitiator.matchesX500(NOTARY.party)) + Assert.assertFalse(testCommsFlowInitiator.matchesX500(DUMMY_BANK_A.party)) + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 9f1701e383..0cb65be579 100644 --- a/settings.gradle +++ b/settings.gradle @@ -58,5 +58,6 @@ include 'samples:simm-valuation-demo:contracts-states' include 'samples:notary-demo' include 'samples:bank-of-corda-demo' include 'samples:cordapp-configuration' +include 'samples:network-verifier' include 'serialization' include 'serialization-deterministic'