Skip to content

Commit f19564f

Browse files
authored
add simple network verification cordapp (corda#3412)
* add simple network verification cordapp * add ability to filter checked counterparties to specific x500
1 parent f103bdc commit f19564f

File tree

5 files changed

+230
-0
lines changed

5 files changed

+230
-0
lines changed

samples/network-verifier/build.gradle

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
apply plugin: 'kotlin'
2+
apply plugin: 'java'
3+
apply plugin: 'net.corda.plugins.cordapp'
4+
apply plugin: 'net.corda.plugins.cordformation'
5+
6+
dependencies {
7+
cordaCompile project(":core")
8+
cordaCompile project(":node-api")
9+
cordaCompile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
10+
11+
testCompile project(":test-utils")
12+
testCompile "junit:junit:$junit_version"
13+
}
14+
15+
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
16+
ext.rpcUsers = [['username': "default", 'password': "default", 'permissions': [ 'ALL' ]]]
17+
18+
directory "./build/nodes"
19+
node {
20+
name "O=Notary Service,L=Zurich,C=CH"
21+
notary = [validating : false]
22+
p2pPort 10002
23+
rpcSettings {
24+
port 10003
25+
adminPort 10004
26+
}
27+
h2Port 20004
28+
}
29+
node {
30+
name "O=Bank A,L=London,C=GB"
31+
p2pPort 10005
32+
cordapps = []
33+
rpcUsers = ext.rpcUsers
34+
rpcSettings {
35+
port 10007
36+
adminPort 10008
37+
}
38+
}
39+
node {
40+
name "O=Bank B,L=New York,C=US"
41+
p2pPort 10009
42+
cordapps = []
43+
rpcUsers = ext.rpcUsers
44+
rpcSettings {
45+
port 10011
46+
adminPort 10012
47+
}
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package net.corda.verification
2+
3+
import co.paralleluniverse.fibers.Suspendable
4+
import net.corda.core.contracts.CommandData
5+
import net.corda.core.contracts.Contract
6+
import net.corda.core.contracts.ContractState
7+
import net.corda.core.flows.*
8+
import net.corda.core.identity.AbstractParty
9+
import net.corda.core.identity.CordaX500Name
10+
import net.corda.core.identity.Party
11+
import net.corda.core.serialization.CordaSerializable
12+
import net.corda.core.transactions.LedgerTransaction
13+
import net.corda.core.transactions.TransactionBuilder
14+
import net.corda.core.utilities.ProgressTracker
15+
import net.corda.core.utilities.unwrap
16+
17+
18+
@StartableByRPC
19+
@InitiatingFlow
20+
class TestCommsFlowInitiator(val x500Name: CordaX500Name? = null) : FlowLogic<List<String>>() {
21+
22+
object SENDING : ProgressTracker.Step("SENDING")
23+
object RECIEVED_ALL : ProgressTracker.Step("RECIEVED_ALL")
24+
object FINALIZING : ProgressTracker.Step("FINALIZING")
25+
26+
override val progressTracker: ProgressTracker = ProgressTracker(SENDING, RECIEVED_ALL, FINALIZING)
27+
28+
@Suspendable
29+
override fun call(): List<String> {
30+
progressTracker.currentStep = SENDING
31+
val responses = serviceHub.networkMapCache.allNodes.map {
32+
it.legalIdentities.first()
33+
}.filterNot {
34+
it in serviceHub.myInfo.legalIdentities
35+
}.filterNot {
36+
it in serviceHub.networkMapCache.notaryIdentities
37+
}.filter(::matchesX500)
38+
.map {
39+
val initiateFlow = initiateFlow(it)
40+
initiateFlow.receive<String>().unwrap { it }
41+
}.toList().also {
42+
progressTracker.currentStep = RECIEVED_ALL
43+
}
44+
val tx = TransactionBuilder(notary = serviceHub.networkMapCache.notaryIdentities.first())
45+
tx.addOutputState(CommsTestState(responses, serviceHub.myInfo.legalIdentities.first()), CommsTestContract::class.qualifiedName!!)
46+
tx.addCommand(CommsTestCommand, serviceHub.myInfo.legalIdentities.first().owningKey)
47+
val signedTx = serviceHub.signInitialTransaction(tx)
48+
subFlow(FinalityFlow(signedTx))
49+
return responses
50+
}
51+
52+
fun matchesX500(it: Party): Boolean {
53+
return x500Name?.equals(it.name) ?: true
54+
}
55+
}
56+
57+
@InitiatedBy(TestCommsFlowInitiator::class)
58+
class TestCommsFlowResponder(val otherSideSession: FlowSession) : FlowLogic<Unit>() {
59+
@Suspendable
60+
override fun call() {
61+
otherSideSession.send("Hello from: " + serviceHub.myInfo.legalIdentities.first().name.toString())
62+
}
63+
64+
}
65+
66+
@CordaSerializable
67+
data class CommsTestState(val responses: List<String>, val issuer: AbstractParty) : ContractState {
68+
override val participants: List<AbstractParty>
69+
get() = listOf(issuer)
70+
71+
}
72+
73+
74+
@CordaSerializable
75+
object CommsTestCommand : CommandData
76+
77+
78+
class CommsTestContract : Contract {
79+
override fun verify(tx: LedgerTransaction) {
80+
}
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package net.corda.verification
2+
3+
import net.corda.core.contracts.CommandData
4+
import net.corda.core.contracts.Contract
5+
import net.corda.core.contracts.ContractState
6+
import net.corda.core.flows.FinalityFlow
7+
import net.corda.core.flows.FlowLogic
8+
import net.corda.core.flows.StartableByRPC
9+
import net.corda.core.identity.AbstractParty
10+
import net.corda.core.serialization.CordaSerializable
11+
import net.corda.core.transactions.LedgerTransaction
12+
import net.corda.core.transactions.TransactionBuilder
13+
import net.corda.core.utilities.ProgressTracker
14+
15+
16+
@StartableByRPC
17+
class TestNotaryFlow : FlowLogic<String>() {
18+
19+
object ISSUING : ProgressTracker.Step("ISSUING")
20+
object ISSUED : ProgressTracker.Step("ISSUED")
21+
object DESTROYING : ProgressTracker.Step("DESTROYING")
22+
object FINALIZED : ProgressTracker.Step("FINALIZED")
23+
24+
override val progressTracker: ProgressTracker = ProgressTracker(ISSUING, ISSUED, DESTROYING, FINALIZED)
25+
26+
27+
override fun call(): String {
28+
val issueBuilder = TransactionBuilder()
29+
val notary = serviceHub.networkMapCache.notaryIdentities.first()
30+
issueBuilder.notary = notary;
31+
val myIdentity = serviceHub.myInfo.legalIdentities.first()
32+
issueBuilder.addOutputState(NotaryTestState(notary.name.toString(), myIdentity), NotaryTestContract::class.qualifiedName!!)
33+
issueBuilder.addCommand(NotaryTestCommand, myIdentity.owningKey)
34+
val signedTx = serviceHub.signInitialTransaction(issueBuilder)
35+
val issueResult = subFlow(FinalityFlow(signedTx))
36+
progressTracker.currentStep = ISSUED
37+
val destroyBuilder = TransactionBuilder()
38+
destroyBuilder.notary = notary;
39+
destroyBuilder.addInputState(issueResult.tx.outRefsOfType<NotaryTestState>().first())
40+
destroyBuilder.addCommand(NotaryTestCommand, myIdentity.owningKey)
41+
val signedDestroyT = serviceHub.signInitialTransaction(destroyBuilder)
42+
val result = subFlow(FinalityFlow(signedDestroyT))
43+
progressTracker.currentStep = DESTROYING
44+
progressTracker.currentStep = FINALIZED
45+
return "notarised: " + result.notary.toString() + "::" + result.tx.id
46+
}
47+
}
48+
49+
50+
@CordaSerializable
51+
data class NotaryTestState(val id: String, val issuer: AbstractParty) : ContractState {
52+
override val participants: List<AbstractParty>
53+
get() = listOf(issuer)
54+
55+
}
56+
57+
58+
@CordaSerializable
59+
object NotaryTestCommand : CommandData
60+
61+
62+
class NotaryTestContract : Contract {
63+
override fun verify(tx: LedgerTransaction) {
64+
}
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package net.corda.configsample
2+
3+
import net.corda.testing.core.ALICE_NAME
4+
import net.corda.testing.core.DUMMY_BANK_A_NAME
5+
import net.corda.testing.core.DUMMY_NOTARY_NAME
6+
import net.corda.testing.core.TestIdentity
7+
import net.corda.verification.TestCommsFlowInitiator
8+
import org.junit.Assert
9+
import org.junit.Test
10+
11+
class TestCommsFlowInitiatorTest {
12+
13+
val ALICE = TestIdentity(ALICE_NAME, 70)
14+
val NOTARY = TestIdentity(DUMMY_NOTARY_NAME, 12)
15+
val DUMMY_BANK_A = TestIdentity(DUMMY_BANK_A_NAME, 3)
16+
17+
@Test
18+
fun `should allow all node infos through if no x500 is passed`() {
19+
val testCommsFlowInitiator = TestCommsFlowInitiator()
20+
21+
Assert.assertTrue(testCommsFlowInitiator.matchesX500(ALICE.party))
22+
Assert.assertTrue(testCommsFlowInitiator.matchesX500(NOTARY.party))
23+
Assert.assertTrue(testCommsFlowInitiator.matchesX500(DUMMY_BANK_A.party))
24+
}
25+
26+
@Test
27+
fun `should allow only specified x500 if no x500 is passed`() {
28+
val testCommsFlowInitiator = TestCommsFlowInitiator(ALICE_NAME)
29+
30+
Assert.assertTrue(testCommsFlowInitiator.matchesX500(ALICE.party))
31+
Assert.assertFalse(testCommsFlowInitiator.matchesX500(NOTARY.party))
32+
Assert.assertFalse(testCommsFlowInitiator.matchesX500(DUMMY_BANK_A.party))
33+
}
34+
}

settings.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,6 @@ include 'samples:simm-valuation-demo:contracts-states'
5858
include 'samples:notary-demo'
5959
include 'samples:bank-of-corda-demo'
6060
include 'samples:cordapp-configuration'
61+
include 'samples:network-verifier'
6162
include 'serialization'
6263
include 'serialization-deterministic'

0 commit comments

Comments
 (0)