add simple network verification cordapp (#3412)

* add simple network verification cordapp

* add ability to filter checked counterparties to specific x500
This commit is contained in:
Stefano Franz 2018-07-04 11:33:21 +01:00 committed by GitHub
parent f103bdc98a
commit f19564f9f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 230 additions and 0 deletions

View File

@ -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
}
}
}

View File

@ -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<List<String>>() {
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<String> {
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<String>().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<Unit>() {
@Suspendable
override fun call() {
otherSideSession.send("Hello from: " + serviceHub.myInfo.legalIdentities.first().name.toString())
}
}
@CordaSerializable
data class CommsTestState(val responses: List<String>, val issuer: AbstractParty) : ContractState {
override val participants: List<AbstractParty>
get() = listOf(issuer)
}
@CordaSerializable
object CommsTestCommand : CommandData
class CommsTestContract : Contract {
override fun verify(tx: LedgerTransaction) {
}
}

View File

@ -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<String>() {
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<NotaryTestState>().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<AbstractParty>
get() = listOf(issuer)
}
@CordaSerializable
object NotaryTestCommand : CommandData
class NotaryTestContract : Contract {
override fun verify(tx: LedgerTransaction) {
}
}

View File

@ -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))
}
}

View File

@ -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'