mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
RAFT notary demo refactoring (#629)
Specifically, make the IDE/driver and gradle/NodeRunner methods of launching the demo behave more similarly, with a view to configuring them the same way. * Add option to driver to nominate a node as network map, so that the driver-based demo doesn't run an additional node * Change gradle ports to match those chosen by driver
This commit is contained in:
parent
e2ce80c8ec
commit
e981632184
@ -1,6 +1,7 @@
|
||||
package net.corda.node
|
||||
|
||||
import com.google.common.base.Stopwatch
|
||||
import net.corda.node.driver.FalseNetworkMap
|
||||
import net.corda.node.driver.driver
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
@ -12,7 +13,7 @@ class NodeStartupPerformanceTests {
|
||||
// Measure the startup time of nodes. Note that this includes an RPC roundtrip, which causes e.g. Kryo initialisation.
|
||||
@Test
|
||||
fun `single node startup time`() {
|
||||
driver(automaticallyStartNetworkMap = false) {
|
||||
driver(networkMapStrategy = FalseNetworkMap) {
|
||||
startNetworkMapService().get()
|
||||
val times = ArrayList<Long>()
|
||||
for (i in 1 .. 10) {
|
||||
|
@ -102,7 +102,7 @@ interface DriverDSLExposedInterface {
|
||||
|
||||
/**
|
||||
* Starts a network map service node. Note that only a single one should ever be running, so you will probably want
|
||||
* to set automaticallyStartNetworkMap to false in your [driver] call.
|
||||
* to set networkMapStrategy to FalseNetworkMap in your [driver] call.
|
||||
*/
|
||||
fun startNetworkMapService(): ListenableFuture<Unit>
|
||||
|
||||
@ -201,7 +201,7 @@ fun <A> driver(
|
||||
debugPortAllocation: PortAllocation = PortAllocation.Incremental(5005),
|
||||
systemProperties: Map<String, String> = emptyMap(),
|
||||
useTestClock: Boolean = false,
|
||||
automaticallyStartNetworkMap: Boolean = true,
|
||||
networkMapStrategy: NetworkMapStrategy = DedicatedNetworkMap,
|
||||
dsl: DriverDSLExposedInterface.() -> A
|
||||
) = genericDriver(
|
||||
driverDsl = DriverDSL(
|
||||
@ -210,7 +210,7 @@ fun <A> driver(
|
||||
systemProperties = systemProperties,
|
||||
driverDirectory = driverDirectory.toAbsolutePath(),
|
||||
useTestClock = useTestClock,
|
||||
automaticallyStartNetworkMap = automaticallyStartNetworkMap,
|
||||
networkMapStrategy = networkMapStrategy,
|
||||
isDebug = isDebug
|
||||
),
|
||||
coerce = { it },
|
||||
@ -412,10 +412,9 @@ class DriverDSL(
|
||||
val driverDirectory: Path,
|
||||
val useTestClock: Boolean,
|
||||
val isDebug: Boolean,
|
||||
val automaticallyStartNetworkMap: Boolean
|
||||
val networkMapStrategy: NetworkMapStrategy
|
||||
) : DriverDSLInternalInterface {
|
||||
private val networkMapLegalName = DUMMY_MAP.name
|
||||
private val networkMapAddress = portAllocation.nextHostAndPort()
|
||||
private val dedicatedNetworkMapAddress = portAllocation.nextHostAndPort()
|
||||
val executorService: ListeningScheduledExecutorService = MoreExecutors.listeningDecorator(
|
||||
Executors.newScheduledThreadPool(2, ThreadFactoryBuilder().setNameFormat("driver-pool-thread-%d").build())
|
||||
)
|
||||
@ -488,10 +487,7 @@ class DriverDSL(
|
||||
"rpcAddress" to rpcAddress.toString(),
|
||||
"webAddress" to webAddress.toString(),
|
||||
"extraAdvertisedServiceIds" to advertisedServices.map { it.toString() },
|
||||
"networkMapService" to mapOf(
|
||||
"address" to networkMapAddress.toString(),
|
||||
"legalName" to networkMapLegalName.toString()
|
||||
),
|
||||
"networkMapService" to networkMapStrategy.serviceConfig(dedicatedNetworkMapAddress, name, p2pAddress),
|
||||
"useTestClock" to useTestClock,
|
||||
"rpcUsers" to rpcUsers.map {
|
||||
mapOf(
|
||||
@ -578,7 +574,7 @@ class DriverDSL(
|
||||
}
|
||||
|
||||
override fun start() {
|
||||
if (automaticallyStartNetworkMap) {
|
||||
if (networkMapStrategy.startDedicated) {
|
||||
startNetworkMapService()
|
||||
}
|
||||
}
|
||||
@ -586,6 +582,7 @@ class DriverDSL(
|
||||
override fun startNetworkMapService(): ListenableFuture<Unit> {
|
||||
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
||||
val apiAddress = portAllocation.nextHostAndPort().toString()
|
||||
val networkMapLegalName = networkMapStrategy.legalName
|
||||
val baseDirectory = driverDirectory / networkMapLegalName.commonName
|
||||
val config = ConfigHelper.loadConfig(
|
||||
baseDirectory = baseDirectory,
|
||||
@ -595,7 +592,7 @@ class DriverDSL(
|
||||
// TODO: remove the webAddress as NMS doesn't need to run a web server. This will cause all
|
||||
// node port numbers to be shifted, so all demos and docs need to be updated accordingly.
|
||||
"webAddress" to apiAddress,
|
||||
"p2pAddress" to networkMapAddress.toString(),
|
||||
"p2pAddress" to dedicatedNetworkMapAddress.toString(),
|
||||
"useTestClock" to useTestClock
|
||||
)
|
||||
)
|
||||
@ -603,7 +600,7 @@ class DriverDSL(
|
||||
log.info("Starting network-map-service")
|
||||
val startNode = startNode(executorService, config.parseAs<FullNodeConfiguration>(), config, quasarJarPath, debugPort, systemProperties)
|
||||
registerProcess(startNode)
|
||||
return startNode.flatMap { addressMustBeBound(executorService, networkMapAddress, it) }
|
||||
return startNode.flatMap { addressMustBeBound(executorService, dedicatedNetworkMapAddress, it) }
|
||||
}
|
||||
|
||||
override fun <A> pollUntilNonNull(pollName: String, pollInterval: Duration, warnCount: Int, check: () -> A?): ListenableFuture<A> {
|
||||
|
@ -0,0 +1,47 @@
|
||||
package net.corda.node.driver
|
||||
|
||||
import com.google.common.net.HostAndPort
|
||||
import net.corda.core.utilities.DUMMY_MAP
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
|
||||
/**
|
||||
* Instruct the driver how to set up the network map, if at all.
|
||||
* @see FalseNetworkMap
|
||||
* @see DedicatedNetworkMap
|
||||
* @see NominatedNetworkMap
|
||||
*/
|
||||
abstract class NetworkMapStrategy(internal val startDedicated: Boolean, internal val legalName: X500Name) {
|
||||
internal abstract fun serviceConfig(dedicatedAddress: HostAndPort, nodeName: X500Name, p2pAddress: HostAndPort): Map<String, String>?
|
||||
}
|
||||
|
||||
private fun toServiceConfig(address: HostAndPort, legalName: X500Name) = mapOf(
|
||||
"address" to address.toString(),
|
||||
"legalName" to legalName.toString()
|
||||
)
|
||||
|
||||
abstract class AbstractDedicatedNetworkMap(start: Boolean) : NetworkMapStrategy(start, DUMMY_MAP.name) {
|
||||
override fun serviceConfig(dedicatedAddress: HostAndPort, nodeName: X500Name, p2pAddress: HostAndPort) = toServiceConfig(dedicatedAddress, legalName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not start a network map.
|
||||
*/
|
||||
object FalseNetworkMap : AbstractDedicatedNetworkMap(false)
|
||||
|
||||
/**
|
||||
* Start a dedicated node to host the network map.
|
||||
*/
|
||||
object DedicatedNetworkMap : AbstractDedicatedNetworkMap(true)
|
||||
|
||||
/**
|
||||
* As in gradle-based demos, nominate a node to host the network map, so that there is one fewer node in total than in the [DedicatedNetworkMap] case.
|
||||
* Will fail if the port you pass in does not match the P2P port the driver assigns to the named node.
|
||||
*/
|
||||
class NominatedNetworkMap(legalName: X500Name, private val address: HostAndPort) : NetworkMapStrategy(false, legalName) {
|
||||
override fun serviceConfig(dedicatedAddress: HostAndPort, nodeName: X500Name, p2pAddress: HostAndPort) = if (nodeName != legalName) {
|
||||
toServiceConfig(address, legalName)
|
||||
} else {
|
||||
p2pAddress == address || throw IllegalArgumentException("Passed-in address $address of nominated network map $legalName is wrong, it should be: $p2pAddress")
|
||||
null
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ apply plugin: 'net.corda.plugins.cordformation'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
ext {
|
||||
deployTo = "./build/nodes"
|
||||
deployTo = "build/nodes"
|
||||
notaryType = "corda.notary.validating.raft"
|
||||
notaryName = "CN=Raft,O=R3,OU=corda,L=Zurich,C=CH"
|
||||
advertisedNotary = "$notaryType|$notaryName"
|
||||
@ -53,7 +53,13 @@ publishing {
|
||||
}
|
||||
}
|
||||
|
||||
task generateNotaryIdentity(type: JavaExec) {
|
||||
task cleanNodes {
|
||||
doLast {
|
||||
delete deployTo
|
||||
}
|
||||
}
|
||||
|
||||
task generateNotaryIdentity(type: JavaExec, dependsOn: 'cleanNodes') {
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
main = "net.corda.node.utilities.ServiceIdentityGeneratorKt"
|
||||
def nodeDirs = ["$deployTo/Notary1",
|
||||
@ -66,7 +72,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', 'generateN
|
||||
directory deployTo
|
||||
networkMap "CN=Notary 1,O=R3,OU=corda,L=London,C=UK"
|
||||
node {
|
||||
name "CN=Party,O=R3,OU=corda,L=London,C=UK"
|
||||
name "CN=Alice Corp,O=Alice Corp,L=London,C=UK"
|
||||
nearestCity "London"
|
||||
advertisedServices = []
|
||||
p2pPort 10002
|
||||
@ -78,7 +84,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', 'generateN
|
||||
]]]
|
||||
}
|
||||
node {
|
||||
name "CN=Counterparty,O=R3,OU=corda,L=London,C=UK"
|
||||
name "CN=Bob Plc,O=Bob Plc,L=London,C=UK"
|
||||
nearestCity "New York"
|
||||
advertisedServices = []
|
||||
p2pPort 10005
|
||||
@ -89,30 +95,30 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', 'generateN
|
||||
name "CN=Notary 1,O=R3,OU=corda,L=London,C=UK"
|
||||
nearestCity "London"
|
||||
advertisedServices = [advertisedNotary]
|
||||
p2pPort 10008
|
||||
rpcPort 10009
|
||||
p2pPort 10009
|
||||
rpcPort 10010
|
||||
cordapps = []
|
||||
notaryNodePort 11002
|
||||
notaryNodePort 10008
|
||||
}
|
||||
node {
|
||||
name "CN=Notary 2,O=R3,OU=corda,L=London,C=UK"
|
||||
nearestCity "London"
|
||||
advertisedServices = [advertisedNotary]
|
||||
p2pPort 10011
|
||||
rpcPort 10012
|
||||
p2pPort 10013
|
||||
rpcPort 10014
|
||||
cordapps = []
|
||||
notaryNodePort 11004
|
||||
notaryClusterAddresses = ["localhost:11002"]
|
||||
notaryNodePort 10012
|
||||
notaryClusterAddresses = ["localhost:10008"]
|
||||
}
|
||||
node {
|
||||
name "CN=Notary 3,O=R3,OU=corda,L=London,C=UK"
|
||||
nearestCity "London"
|
||||
advertisedServices = [advertisedNotary]
|
||||
p2pPort 10014
|
||||
rpcPort 10015
|
||||
p2pPort 10017
|
||||
rpcPort 10018
|
||||
cordapps = []
|
||||
notaryNodePort 11006
|
||||
notaryClusterAddresses = ["localhost:11002"]
|
||||
notaryNodePort 10016
|
||||
notaryClusterAddresses = ["localhost:10008"]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,22 +1,30 @@
|
||||
package net.corda.notarydemo
|
||||
|
||||
import com.google.common.net.HostAndPort
|
||||
import net.corda.core.crypto.appendToCommonName
|
||||
import net.corda.core.div
|
||||
import net.corda.core.utilities.ALICE
|
||||
import net.corda.core.utilities.BOB
|
||||
import net.corda.core.utilities.DUMMY_NOTARY
|
||||
import net.corda.flows.NotaryFlow
|
||||
import net.corda.node.driver.NominatedNetworkMap
|
||||
import net.corda.node.driver.PortAllocation
|
||||
import net.corda.node.driver.driver
|
||||
import net.corda.node.services.startFlowPermission
|
||||
import net.corda.node.services.transactions.RaftValidatingNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.notarydemo.flows.DummyIssueAndMove
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import java.nio.file.Paths
|
||||
|
||||
/** Creates and starts all nodes required for the demo. */
|
||||
fun main(args: Array<String>) {
|
||||
val demoUser = listOf(User("demo", "demo", setOf("StartFlow.net.corda.notarydemo.flows.DummyIssueAndMove", "StartFlow.net.corda.flows.NotaryFlow\$Client")))
|
||||
driver(isDebug = true, driverDirectory = Paths.get("build") / "notary-demo-nodes") {
|
||||
val demoUser = listOf(User("demo", "demo", setOf(startFlowPermission<DummyIssueAndMove>(), startFlowPermission<NotaryFlow.Client>())))
|
||||
val networkMap = NominatedNetworkMap(DUMMY_NOTARY.name.appendToCommonName("1"), HostAndPort.fromParts("localhost", 10009))
|
||||
driver(isDebug = true, driverDirectory = Paths.get("build") / "notary-demo-nodes", networkMapStrategy = networkMap, portAllocation = PortAllocation.Incremental(10001)) {
|
||||
startNode(ALICE.name, rpcUsers = demoUser)
|
||||
startNode(BOB.name)
|
||||
startNotaryCluster(DUMMY_NOTARY.name, clusterSize = 3, type = RaftValidatingNotaryService.type)
|
||||
startNotaryCluster(X500Name("CN=Raft,O=R3,OU=corda,L=Zurich,C=CH"), clusterSize = 3, type = RaftValidatingNotaryService.type)
|
||||
waitForAllNodesToFinish()
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import net.corda.core.getOrThrow
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.BOB
|
||||
import net.corda.flows.NotaryFlow
|
||||
import net.corda.nodeapi.config.SSLConfiguration
|
||||
import net.corda.notarydemo.flows.DummyIssueAndMove
|
||||
@ -39,7 +40,7 @@ private class NotaryDemoClientApi(val rpc: CordaRPCOps) {
|
||||
private val counterpartyNode by lazy {
|
||||
val (parties, partyUpdates) = rpc.networkMapUpdates()
|
||||
partyUpdates.notUsed()
|
||||
parties.first { it.legalIdentity.name == X500Name("CN=Counterparty,O=R3,OU=corda,L=London,C=UK") }
|
||||
parties.first { it.legalIdentity.name == BOB.name }
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
@ -108,9 +108,11 @@ task npmInstall(type: Exec) {
|
||||
outputs.upToDateWhen { file('src/main/web/node_modules').exists() }
|
||||
}
|
||||
|
||||
task cleanWeb() << {
|
||||
delete 'src/main/resources/simmvaluationweb'
|
||||
delete 'src/main/web/dist'
|
||||
task cleanWeb() {
|
||||
doLast {
|
||||
delete 'src/main/resources/simmvaluationweb'
|
||||
delete 'src/main/web/dist'
|
||||
}
|
||||
}
|
||||
|
||||
task buildWeb(type: Exec, dependsOn: [cleanWeb, npmInstall]) {
|
||||
|
@ -194,7 +194,7 @@ fun <A> rpcDriver(
|
||||
debugPortAllocation: PortAllocation = globalDebugPortAllocation,
|
||||
systemProperties: Map<String, String> = emptyMap(),
|
||||
useTestClock: Boolean = false,
|
||||
automaticallyStartNetworkMap: Boolean = false,
|
||||
networkMapStrategy: NetworkMapStrategy = FalseNetworkMap,
|
||||
dsl: RPCDriverExposedDSLInterface.() -> A
|
||||
) = genericDriver(
|
||||
driverDsl = RPCDriverDSL(
|
||||
@ -204,7 +204,7 @@ fun <A> rpcDriver(
|
||||
systemProperties = systemProperties,
|
||||
driverDirectory = driverDirectory.toAbsolutePath(),
|
||||
useTestClock = useTestClock,
|
||||
automaticallyStartNetworkMap = automaticallyStartNetworkMap,
|
||||
networkMapStrategy = networkMapStrategy,
|
||||
isDebug = isDebug
|
||||
)
|
||||
),
|
||||
|
@ -78,7 +78,7 @@ fun <A> verifierDriver(
|
||||
debugPortAllocation: PortAllocation = PortAllocation.Incremental(5005),
|
||||
systemProperties: Map<String, String> = emptyMap(),
|
||||
useTestClock: Boolean = false,
|
||||
automaticallyStartNetworkMap: Boolean = true,
|
||||
networkMapStrategy: NetworkMapStrategy = DedicatedNetworkMap,
|
||||
dsl: VerifierExposedDSLInterface.() -> A
|
||||
) = genericDriver(
|
||||
driverDsl = VerifierDriverDSL(
|
||||
@ -88,7 +88,7 @@ fun <A> verifierDriver(
|
||||
systemProperties = systemProperties,
|
||||
driverDirectory = driverDirectory.toAbsolutePath(),
|
||||
useTestClock = useTestClock,
|
||||
automaticallyStartNetworkMap = automaticallyStartNetworkMap,
|
||||
networkMapStrategy = networkMapStrategy,
|
||||
isDebug = isDebug
|
||||
)
|
||||
),
|
||||
|
@ -13,6 +13,7 @@ import net.corda.core.utilities.ALICE
|
||||
import net.corda.core.utilities.DUMMY_NOTARY
|
||||
import net.corda.flows.CashIssueFlow
|
||||
import net.corda.flows.CashPaymentFlow
|
||||
import net.corda.node.driver.FalseNetworkMap
|
||||
import net.corda.node.services.config.VerifierType
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import org.junit.Test
|
||||
@ -34,7 +35,7 @@ class VerifierTests {
|
||||
|
||||
@Test
|
||||
fun `single verifier works with requestor`() {
|
||||
verifierDriver(automaticallyStartNetworkMap = false) {
|
||||
verifierDriver(networkMapStrategy = FalseNetworkMap) {
|
||||
val aliceFuture = startVerificationRequestor(ALICE.name)
|
||||
val transactions = generateTransactions(100)
|
||||
val alice = aliceFuture.get()
|
||||
@ -51,7 +52,7 @@ class VerifierTests {
|
||||
|
||||
@Test
|
||||
fun `multiple verifiers work with requestor`() {
|
||||
verifierDriver(automaticallyStartNetworkMap = false) {
|
||||
verifierDriver(networkMapStrategy = FalseNetworkMap) {
|
||||
val aliceFuture = startVerificationRequestor(ALICE.name)
|
||||
val transactions = generateTransactions(100)
|
||||
val alice = aliceFuture.get()
|
||||
@ -71,7 +72,7 @@ class VerifierTests {
|
||||
|
||||
@Test
|
||||
fun `verification redistributes on verifier death`() {
|
||||
verifierDriver(automaticallyStartNetworkMap = false) {
|
||||
verifierDriver(networkMapStrategy = FalseNetworkMap) {
|
||||
val aliceFuture = startVerificationRequestor(ALICE.name)
|
||||
val numberOfTransactions = 100
|
||||
val transactions = generateTransactions(numberOfTransactions)
|
||||
@ -99,7 +100,7 @@ class VerifierTests {
|
||||
|
||||
@Test
|
||||
fun `verification request waits until verifier comes online`() {
|
||||
verifierDriver(automaticallyStartNetworkMap = false) {
|
||||
verifierDriver(networkMapStrategy = FalseNetworkMap) {
|
||||
val aliceFuture = startVerificationRequestor(ALICE.name)
|
||||
val transactions = generateTransactions(100)
|
||||
val alice = aliceFuture.get()
|
||||
|
Loading…
Reference in New Issue
Block a user