mirror of
https://github.com/corda/corda.git
synced 2025-06-01 23:20:54 +00:00
Fix node integration tests. (#2233)
* Add tests for node registration and communication
This commit is contained in:
parent
ff8d0881b3
commit
6db0490750
@ -10,7 +10,6 @@ import net.corda.core.messaging.CordaRPCOps
|
|||||||
import net.corda.core.serialization.SerializationWhitelist
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.ProgressTracker
|
import net.corda.core.utilities.ProgressTracker
|
||||||
import net.corda.webserver.services.WebServerPluginRegistry
|
|
||||||
import java.util.function.Function
|
import java.util.function.Function
|
||||||
import javax.ws.rs.GET
|
import javax.ws.rs.GET
|
||||||
import javax.ws.rs.Path
|
import javax.ws.rs.Path
|
||||||
|
@ -10,6 +10,7 @@ import net.corda.core.utilities.seconds
|
|||||||
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
|
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
|
||||||
import net.corda.nodeapi.internal.network.NetworkParameters
|
import net.corda.nodeapi.internal.network.NetworkParameters
|
||||||
import net.corda.testing.ALICE_NAME
|
import net.corda.testing.ALICE_NAME
|
||||||
|
import net.corda.testing.ROOT_CA
|
||||||
import net.corda.testing.BOB_NAME
|
import net.corda.testing.BOB_NAME
|
||||||
import net.corda.testing.SerializationEnvironmentRule
|
import net.corda.testing.SerializationEnvironmentRule
|
||||||
import net.corda.testing.driver.NodeHandle
|
import net.corda.testing.driver.NodeHandle
|
||||||
@ -49,20 +50,22 @@ class NetworkMapTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `node correctly downloads and saves network parameters file on startup`() {
|
fun `node correctly downloads and saves network parameters file on startup`() {
|
||||||
internalDriver(portAllocation = portAllocation, compatibilityZone = compatibilityZone, initialiseSerialization = false) {
|
internalDriver(portAllocation = portAllocation, compatibilityZone = compatibilityZone,
|
||||||
|
initialiseSerialization = false, notarySpecs = emptyList()) {
|
||||||
val alice = startNode(providedName = ALICE_NAME).getOrThrow()
|
val alice = startNode(providedName = ALICE_NAME).getOrThrow()
|
||||||
val networkParameters = alice.configuration.baseDirectory
|
val networkParameters = alice.configuration.baseDirectory
|
||||||
.list { paths -> paths.filter { it.fileName.toString() == NETWORK_PARAMS_FILE_NAME }.findFirst().get() }
|
.list { paths -> paths.filter { it.fileName.toString() == NETWORK_PARAMS_FILE_NAME }.findFirst().get() }
|
||||||
.readAll()
|
.readAll()
|
||||||
.deserialize<SignedData<NetworkParameters>>()
|
.deserialize<SignedData<NetworkParameters>>()
|
||||||
.verified()
|
.verified()
|
||||||
assertEquals(NetworkMapServer.stubNetworkParameter, networkParameters)
|
assertEquals(networkMapServer.networkParameters, networkParameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `nodes can see each other using the http network map`() {
|
fun `nodes can see each other using the http network map`() {
|
||||||
internalDriver(portAllocation = portAllocation, compatibilityZone = compatibilityZone, initialiseSerialization = false) {
|
internalDriver(portAllocation = portAllocation, compatibilityZone = compatibilityZone,
|
||||||
|
initialiseSerialization = false, onNetworkParametersGeneration = { networkMapServer.networkParameters = it }) {
|
||||||
val alice = startNode(providedName = ALICE_NAME)
|
val alice = startNode(providedName = ALICE_NAME)
|
||||||
val bob = startNode(providedName = BOB_NAME)
|
val bob = startNode(providedName = BOB_NAME)
|
||||||
val notaryNode = defaultNotaryNode.get()
|
val notaryNode = defaultNotaryNode.get()
|
||||||
@ -77,7 +80,8 @@ class NetworkMapTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `nodes process network map add updates correctly when adding new node to network map`() {
|
fun `nodes process network map add updates correctly when adding new node to network map`() {
|
||||||
internalDriver(portAllocation = portAllocation, compatibilityZone = compatibilityZone, initialiseSerialization = false) {
|
internalDriver(portAllocation = portAllocation, compatibilityZone = compatibilityZone,
|
||||||
|
initialiseSerialization = false, onNetworkParametersGeneration = { networkMapServer.networkParameters = it }) {
|
||||||
val alice = startNode(providedName = ALICE_NAME)
|
val alice = startNode(providedName = ALICE_NAME)
|
||||||
val notaryNode = defaultNotaryNode.get()
|
val notaryNode = defaultNotaryNode.get()
|
||||||
val aliceNode = alice.get()
|
val aliceNode = alice.get()
|
||||||
@ -98,7 +102,8 @@ class NetworkMapTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `nodes process network map remove updates correctly`() {
|
fun `nodes process network map remove updates correctly`() {
|
||||||
internalDriver(portAllocation = portAllocation, compatibilityZone = compatibilityZone, initialiseSerialization = false) {
|
internalDriver(portAllocation = portAllocation, compatibilityZone = compatibilityZone,
|
||||||
|
initialiseSerialization = false, onNetworkParametersGeneration = { networkMapServer.networkParameters = it }) {
|
||||||
val alice = startNode(providedName = ALICE_NAME)
|
val alice = startNode(providedName = ALICE_NAME)
|
||||||
val bob = startNode(providedName = BOB_NAME)
|
val bob = startNode(providedName = BOB_NAME)
|
||||||
val notaryNode = defaultNotaryNode.get()
|
val notaryNode = defaultNotaryNode.get()
|
||||||
|
@ -3,10 +3,12 @@ package net.corda.node.utilities.registration
|
|||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.cert
|
import net.corda.core.internal.cert
|
||||||
|
import net.corda.core.internal.concurrent.transpose
|
||||||
import net.corda.core.internal.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.*
|
||||||
import net.corda.core.utilities.minutes
|
import net.corda.finance.DOLLARS
|
||||||
|
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
||||||
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
||||||
import net.corda.nodeapi.internal.crypto.CertificateType
|
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||||
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||||
@ -14,11 +16,16 @@ import net.corda.nodeapi.internal.crypto.X509Utilities
|
|||||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA
|
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_INTERMEDIATE_CA
|
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_INTERMEDIATE_CA
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
|
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
|
||||||
|
import net.corda.nodeapi.internal.network.NotaryInfo
|
||||||
|
import net.corda.testing.ROOT_CA
|
||||||
import net.corda.testing.SerializationEnvironmentRule
|
import net.corda.testing.SerializationEnvironmentRule
|
||||||
import net.corda.testing.node.internal.CompatibilityZoneParams
|
|
||||||
import net.corda.testing.driver.PortAllocation
|
import net.corda.testing.driver.PortAllocation
|
||||||
|
import net.corda.testing.node.NotarySpec
|
||||||
|
import net.corda.testing.node.internal.CompatibilityZoneParams
|
||||||
import net.corda.testing.node.internal.internalDriver
|
import net.corda.testing.node.internal.internalDriver
|
||||||
import net.corda.testing.node.internal.network.NetworkMapServer
|
import net.corda.testing.node.internal.network.NetworkMapServer
|
||||||
|
import net.corda.testing.singleIdentity
|
||||||
|
import net.corda.testing.singleIdentityAndCert
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.bouncycastle.pkcs.PKCS10CertificationRequest
|
import org.bouncycastle.pkcs.PKCS10CertificationRequest
|
||||||
@ -44,15 +51,13 @@ class NodeRegistrationTest {
|
|||||||
@JvmField
|
@JvmField
|
||||||
val testSerialization = SerializationEnvironmentRule(true)
|
val testSerialization = SerializationEnvironmentRule(true)
|
||||||
private val portAllocation = PortAllocation.Incremental(13000)
|
private val portAllocation = PortAllocation.Incremental(13000)
|
||||||
private val rootCertAndKeyPair = createSelfKeyAndSelfSignedCertificate()
|
private val registrationHandler = RegistrationHandler(ROOT_CA)
|
||||||
private val registrationHandler = RegistrationHandler(rootCertAndKeyPair)
|
|
||||||
|
|
||||||
private lateinit var server: NetworkMapServer
|
private lateinit var server: NetworkMapServer
|
||||||
private lateinit var serverHostAndPort: NetworkHostAndPort
|
private lateinit var serverHostAndPort: NetworkHostAndPort
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun startServer() {
|
fun startServer() {
|
||||||
server = NetworkMapServer(1.minutes, portAllocation.nextHostAndPort(), rootCertAndKeyPair, registrationHandler)
|
server = NetworkMapServer(1.minutes, portAllocation.nextHostAndPort(), ROOT_CA, "localhost", registrationHandler)
|
||||||
serverHostAndPort = server.start()
|
serverHostAndPort = server.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,19 +66,47 @@ class NodeRegistrationTest {
|
|||||||
server.close()
|
server.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Ideally this test should be checking that two nodes that register are able to transact with each other. However
|
|
||||||
// starting a second node hangs so that needs to be fixed.
|
|
||||||
@Test
|
@Test
|
||||||
fun `node registration correct root cert`() {
|
fun `node registration correct root cert`() {
|
||||||
val compatibilityZone = CompatibilityZoneParams(URL("http://$serverHostAndPort"), rootCert = rootCertAndKeyPair.certificate.cert)
|
val compatibilityZone = CompatibilityZoneParams(URL("http://$serverHostAndPort"), rootCert = ROOT_CA.certificate.cert)
|
||||||
internalDriver(
|
internalDriver(
|
||||||
portAllocation = portAllocation,
|
portAllocation = portAllocation,
|
||||||
notarySpecs = emptyList(),
|
|
||||||
compatibilityZone = compatibilityZone,
|
compatibilityZone = compatibilityZone,
|
||||||
initialiseSerialization = false
|
initialiseSerialization = false,
|
||||||
|
notarySpecs = listOf(NotarySpec(CordaX500Name(organisation = "NotaryService", locality = "Zurich", country = "CH"), validating = false)),
|
||||||
|
extraCordappPackagesToScan = listOf("net.corda.finance"),
|
||||||
|
onNetworkParametersGeneration = { server.networkParameters = it }
|
||||||
) {
|
) {
|
||||||
startNode(providedName = CordaX500Name("Alice", "London", "GB")).getOrThrow()
|
val notary = defaultNotaryNode.get()
|
||||||
assertThat(registrationHandler.idsPolled).contains("Alice")
|
|
||||||
|
val ALICE_NAME = "Alice"
|
||||||
|
val GENEVIEVE_NAME = "Genevieve"
|
||||||
|
val nodesFutures = listOf(startNode(providedName = CordaX500Name(ALICE_NAME, "London", "GB")),
|
||||||
|
startNode(providedName = CordaX500Name(GENEVIEVE_NAME, "London", "GB")))
|
||||||
|
|
||||||
|
val (alice, genevieve) = nodesFutures.transpose().get()
|
||||||
|
val nodes = listOf(alice, genevieve, notary)
|
||||||
|
|
||||||
|
assertThat(registrationHandler.idsPolled).contains(ALICE_NAME, GENEVIEVE_NAME)
|
||||||
|
// Notary identities are generated beforehand hence notary nodes don't go through registration.
|
||||||
|
// This test isn't specifically testing this, or relying on this behavior, though if this check fail,
|
||||||
|
// this will probably lead to the rest of the test to fail.
|
||||||
|
assertThat(registrationHandler.idsPolled).doesNotContain("NotaryService")
|
||||||
|
|
||||||
|
// Check each node has each other identity in their network map cache.
|
||||||
|
val nodeIdentities = nodes.map { it.nodeInfo.singleIdentity() }
|
||||||
|
for (node in nodes) {
|
||||||
|
assertThat(node.rpc.networkMapSnapshot().map { it.singleIdentity() }).containsAll(nodeIdentities)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check we nodes communicate among themselves (and the notary).
|
||||||
|
val anonymous = false
|
||||||
|
genevieve.rpc.startFlow(::CashIssueAndPaymentFlow, 1000.DOLLARS, OpaqueBytes.of(12),
|
||||||
|
alice.nodeInfo.singleIdentity(),
|
||||||
|
anonymous,
|
||||||
|
notary.nodeInfo.singleIdentity())
|
||||||
|
.returnValue
|
||||||
|
.getOrThrow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +118,7 @@ class NodeRegistrationTest {
|
|||||||
portAllocation = portAllocation,
|
portAllocation = portAllocation,
|
||||||
notarySpecs = emptyList(),
|
notarySpecs = emptyList(),
|
||||||
compatibilityZone = compatibilityZone,
|
compatibilityZone = compatibilityZone,
|
||||||
|
initialiseSerialization = false,
|
||||||
// Changing the content of the truststore makes the node fail in a number of ways if started out process.
|
// Changing the content of the truststore makes the node fail in a number of ways if started out process.
|
||||||
startNodesInProcess = true
|
startNodesInProcess = true
|
||||||
) {
|
) {
|
||||||
|
@ -5,10 +5,7 @@ import net.corda.core.crypto.sha256
|
|||||||
import net.corda.core.internal.cert
|
import net.corda.core.internal.cert
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.testing.ALICE_NAME
|
import net.corda.testing.*
|
||||||
import net.corda.testing.BOB_NAME
|
|
||||||
import net.corda.testing.DEV_TRUST_ROOT
|
|
||||||
import net.corda.testing.SerializationEnvironmentRule
|
|
||||||
import net.corda.testing.driver.PortAllocation
|
import net.corda.testing.driver.PortAllocation
|
||||||
import net.corda.testing.internal.createNodeInfoAndSigned
|
import net.corda.testing.internal.createNodeInfoAndSigned
|
||||||
import net.corda.testing.node.internal.network.NetworkMapServer
|
import net.corda.testing.node.internal.network.NetworkMapServer
|
||||||
@ -33,7 +30,7 @@ class NetworkMapClientTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
server = NetworkMapServer(cacheTimeout, PortAllocation.Incremental(10000).nextHostAndPort())
|
server = NetworkMapServer(cacheTimeout, PortAllocation.Incremental(10000).nextHostAndPort(), root_ca = ROOT_CA)
|
||||||
val hostAndPort = server.start()
|
val hostAndPort = server.start()
|
||||||
networkMapClient = NetworkMapClient(URL("http://${hostAndPort.host}:${hostAndPort.port}"), DEV_TRUST_ROOT.cert)
|
networkMapClient = NetworkMapClient(URL("http://${hostAndPort.host}:${hostAndPort.port}"), DEV_TRUST_ROOT.cert)
|
||||||
}
|
}
|
||||||
@ -70,7 +67,7 @@ class NetworkMapClientTest {
|
|||||||
// The test server returns same network parameter for any hash.
|
// The test server returns same network parameter for any hash.
|
||||||
val networkParameter = networkMapClient.getNetworkParameter(SecureHash.randomSHA256())?.verified()
|
val networkParameter = networkMapClient.getNetworkParameter(SecureHash.randomSHA256())?.verified()
|
||||||
assertNotNull(networkParameter)
|
assertNotNull(networkParameter)
|
||||||
assertEquals(NetworkMapServer.stubNetworkParameter, networkParameter)
|
assertEquals(server.networkParameters, networkParameter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -193,7 +193,8 @@ fun <A> driver(
|
|||||||
notarySpecs = notarySpecs,
|
notarySpecs = notarySpecs,
|
||||||
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
||||||
jmxPolicy = jmxPolicy,
|
jmxPolicy = jmxPolicy,
|
||||||
compatibilityZone = null
|
compatibilityZone = null,
|
||||||
|
onNetworkParametersGeneration = { }
|
||||||
),
|
),
|
||||||
coerce = { it },
|
coerce = { it },
|
||||||
dsl = dsl,
|
dsl = dsl,
|
||||||
|
@ -10,13 +10,12 @@ import net.corda.cordform.CordformContext
|
|||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.concurrent.firstOf
|
import net.corda.core.concurrent.firstOf
|
||||||
|
import net.corda.core.crypto.generateKeyPair
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.ThreadBox
|
import net.corda.core.identity.Party
|
||||||
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.concurrent.*
|
import net.corda.core.internal.concurrent.*
|
||||||
import net.corda.core.internal.copyTo
|
|
||||||
import net.corda.core.internal.createDirectories
|
|
||||||
import net.corda.core.internal.div
|
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.node.services.NetworkMapCache
|
import net.corda.core.node.services.NetworkMapCache
|
||||||
import net.corda.core.toFuture
|
import net.corda.core.toFuture
|
||||||
@ -32,6 +31,7 @@ import net.corda.node.services.config.*
|
|||||||
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
|
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
|
||||||
import net.corda.node.utilities.registration.NetworkRegistrationHelper
|
import net.corda.node.utilities.registration.NetworkRegistrationHelper
|
||||||
import net.corda.nodeapi.internal.IdentityGenerator
|
import net.corda.nodeapi.internal.IdentityGenerator
|
||||||
|
import net.corda.nodeapi.internal.IdentityGenerator.NODE_IDENTITY_ALIAS_PREFIX
|
||||||
import net.corda.nodeapi.internal.addShutdownHook
|
import net.corda.nodeapi.internal.addShutdownHook
|
||||||
import net.corda.nodeapi.internal.config.User
|
import net.corda.nodeapi.internal.config.User
|
||||||
import net.corda.nodeapi.internal.config.parseAs
|
import net.corda.nodeapi.internal.config.parseAs
|
||||||
@ -46,6 +46,8 @@ import net.corda.nodeapi.internal.network.NotaryInfo
|
|||||||
import net.corda.testing.ALICE_NAME
|
import net.corda.testing.ALICE_NAME
|
||||||
import net.corda.testing.BOB_NAME
|
import net.corda.testing.BOB_NAME
|
||||||
import net.corda.testing.DUMMY_BANK_A_NAME
|
import net.corda.testing.DUMMY_BANK_A_NAME
|
||||||
|
import net.corda.nodeapi.internal.crypto.*
|
||||||
|
import net.corda.nodeapi.internal.network.NetworkParameters
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
import net.corda.testing.driver.*
|
import net.corda.testing.driver.*
|
||||||
import net.corda.testing.node.ClusterSpec
|
import net.corda.testing.node.ClusterSpec
|
||||||
@ -89,7 +91,8 @@ class DriverDSLImpl(
|
|||||||
extraCordappPackagesToScan: List<String>,
|
extraCordappPackagesToScan: List<String>,
|
||||||
val jmxPolicy: JmxPolicy,
|
val jmxPolicy: JmxPolicy,
|
||||||
val notarySpecs: List<NotarySpec>,
|
val notarySpecs: List<NotarySpec>,
|
||||||
val compatibilityZone: CompatibilityZoneParams?
|
val compatibilityZone: CompatibilityZoneParams?,
|
||||||
|
val onNetworkParametersGeneration: (NetworkParameters) -> Unit
|
||||||
) : InternalDriverDSL {
|
) : InternalDriverDSL {
|
||||||
private var _executorService: ScheduledExecutorService? = null
|
private var _executorService: ScheduledExecutorService? = null
|
||||||
val executorService get() = _executorService!!
|
val executorService get() = _executorService!!
|
||||||
@ -104,7 +107,8 @@ class DriverDSLImpl(
|
|||||||
private val countObservables = mutableMapOf<CordaX500Name, Observable<Int>>()
|
private val countObservables = mutableMapOf<CordaX500Name, Observable<Int>>()
|
||||||
private lateinit var _notaries: List<NotaryHandle>
|
private lateinit var _notaries: List<NotaryHandle>
|
||||||
override val notaryHandles: List<NotaryHandle> get() = _notaries
|
override val notaryHandles: List<NotaryHandle> get() = _notaries
|
||||||
private var networkParameters: NetworkParametersCopier? = null
|
private var networkParametersCopier: NetworkParametersCopier? = null
|
||||||
|
lateinit var networkParameters: NetworkParameters
|
||||||
|
|
||||||
class State {
|
class State {
|
||||||
val processes = ArrayList<Process>()
|
val processes = ArrayList<Process>()
|
||||||
@ -179,8 +183,8 @@ class DriverDSLImpl(
|
|||||||
val p2pAddress = portAllocation.nextHostAndPort()
|
val p2pAddress = portAllocation.nextHostAndPort()
|
||||||
// TODO: Derive name from the full picked name, don't just wrap the common name
|
// TODO: Derive name from the full picked name, don't just wrap the common name
|
||||||
val name = providedName ?: CordaX500Name(organisation = "${oneOf(names).organisation}-${p2pAddress.port}", locality = "London", country = "GB")
|
val name = providedName ?: CordaX500Name(organisation = "${oneOf(names).organisation}-${p2pAddress.port}", locality = "London", country = "GB")
|
||||||
|
val isNotary = name in notarySpecs.map { it.name }
|
||||||
val registrationFuture = if (compatibilityZone?.rootCert != null) {
|
val registrationFuture = if (compatibilityZone?.rootCert != null && !isNotary) {
|
||||||
nodeRegistration(name, compatibilityZone.rootCert, compatibilityZone.url)
|
nodeRegistration(name, compatibilityZone.rootCert, compatibilityZone.url)
|
||||||
} else {
|
} else {
|
||||||
doneFuture(Unit)
|
doneFuture(Unit)
|
||||||
@ -279,7 +283,9 @@ class DriverDSLImpl(
|
|||||||
notaryInfos += NotaryInfo(identity, type.validating)
|
notaryInfos += NotaryInfo(identity, type.validating)
|
||||||
}
|
}
|
||||||
|
|
||||||
networkParameters = NetworkParametersCopier(testNetworkParameters(notaryInfos))
|
networkParameters = testNetworkParameters(notaryInfos)
|
||||||
|
onNetworkParametersGeneration(networkParameters)
|
||||||
|
networkParametersCopier = NetworkParametersCopier(networkParameters)
|
||||||
|
|
||||||
return cordforms.map {
|
return cordforms.map {
|
||||||
val startedNode = startCordformNode(it)
|
val startedNode = startCordformNode(it)
|
||||||
@ -347,8 +353,10 @@ class DriverDSLImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val notaryInfos = generateNotaryIdentities()
|
val notaryInfos = generateNotaryIdentities()
|
||||||
|
networkParameters = testNetworkParameters(notaryInfos)
|
||||||
|
onNetworkParametersGeneration(networkParameters)
|
||||||
// The network parameters must be serialised before starting any of the nodes
|
// The network parameters must be serialised before starting any of the nodes
|
||||||
if (compatibilityZone == null) networkParameters = NetworkParametersCopier(testNetworkParameters(notaryInfos))
|
networkParametersCopier = NetworkParametersCopier(networkParameters)
|
||||||
val nodeHandles = startNotaries()
|
val nodeHandles = startNotaries()
|
||||||
_notaries = notaryInfos.zip(nodeHandles) { (identity, validating), nodes -> NotaryHandle(identity, validating, nodes) }
|
_notaries = notaryInfos.zip(nodeHandles) { (identity, validating), nodes -> NotaryHandle(identity, validating, nodes) }
|
||||||
}
|
}
|
||||||
@ -504,7 +512,11 @@ class DriverDSLImpl(
|
|||||||
val configuration = config.parseAsNodeConfiguration()
|
val configuration = config.parseAsNodeConfiguration()
|
||||||
val baseDirectory = configuration.baseDirectory.createDirectories()
|
val baseDirectory = configuration.baseDirectory.createDirectories()
|
||||||
nodeInfoFilesCopier?.addConfig(baseDirectory)
|
nodeInfoFilesCopier?.addConfig(baseDirectory)
|
||||||
networkParameters?.install(baseDirectory)
|
if (configuration.myLegalName in networkParameters.notaries.map { it.identity.name } || compatibilityZone == null) {
|
||||||
|
// If a notary is being started, then its identity appears in networkParameters (generated by Driver),
|
||||||
|
// and Driver itself must pass the network parameters to the notary.
|
||||||
|
networkParametersCopier?.install(baseDirectory)
|
||||||
|
}
|
||||||
val onNodeExit: () -> Unit = {
|
val onNodeExit: () -> Unit = {
|
||||||
nodeInfoFilesCopier?.removeConfig(baseDirectory)
|
nodeInfoFilesCopier?.removeConfig(baseDirectory)
|
||||||
countObservables.remove(configuration.myLegalName)
|
countObservables.remove(configuration.myLegalName)
|
||||||
@ -817,7 +829,8 @@ fun <DI : DriverDSL, D : InternalDriverDSL, A> genericDriver(
|
|||||||
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
||||||
jmxPolicy = jmxPolicy,
|
jmxPolicy = jmxPolicy,
|
||||||
notarySpecs = notarySpecs,
|
notarySpecs = notarySpecs,
|
||||||
compatibilityZone = null
|
compatibilityZone = null,
|
||||||
|
onNetworkParametersGeneration = {}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val shutdownHook = addShutdownHook(driverDsl::shutdown)
|
val shutdownHook = addShutdownHook(driverDsl::shutdown)
|
||||||
@ -855,6 +868,7 @@ fun <A> internalDriver(
|
|||||||
extraCordappPackagesToScan: List<String> = DriverParameters().extraCordappPackagesToScan,
|
extraCordappPackagesToScan: List<String> = DriverParameters().extraCordappPackagesToScan,
|
||||||
jmxPolicy: JmxPolicy = DriverParameters().jmxPolicy,
|
jmxPolicy: JmxPolicy = DriverParameters().jmxPolicy,
|
||||||
compatibilityZone: CompatibilityZoneParams? = null,
|
compatibilityZone: CompatibilityZoneParams? = null,
|
||||||
|
onNetworkParametersGeneration: (NetworkParameters) -> Unit = {},
|
||||||
dsl: DriverDSLImpl.() -> A
|
dsl: DriverDSLImpl.() -> A
|
||||||
): A {
|
): A {
|
||||||
return genericDriver(
|
return genericDriver(
|
||||||
@ -870,7 +884,8 @@ fun <A> internalDriver(
|
|||||||
notarySpecs = notarySpecs,
|
notarySpecs = notarySpecs,
|
||||||
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
||||||
jmxPolicy = jmxPolicy,
|
jmxPolicy = jmxPolicy,
|
||||||
compatibilityZone = compatibilityZone
|
compatibilityZone = compatibilityZone,
|
||||||
|
onNetworkParametersGeneration = onNetworkParametersGeneration
|
||||||
),
|
),
|
||||||
coerce = { it },
|
coerce = { it },
|
||||||
dsl = dsl,
|
dsl = dsl,
|
||||||
|
@ -121,7 +121,8 @@ fun <A> rpcDriver(
|
|||||||
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
||||||
notarySpecs = notarySpecs,
|
notarySpecs = notarySpecs,
|
||||||
jmxPolicy = jmxPolicy,
|
jmxPolicy = jmxPolicy,
|
||||||
compatibilityZone = null
|
compatibilityZone = null,
|
||||||
|
onNetworkParametersGeneration = {}
|
||||||
), externalTrace
|
), externalTrace
|
||||||
),
|
),
|
||||||
coerce = { it },
|
coerce = { it },
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
package net.corda.testing.node.internal.network
|
package net.corda.testing.node.internal.network
|
||||||
|
|
||||||
|
import net.corda.core.crypto.Crypto
|
||||||
|
import net.corda.core.crypto.SecureHash
|
||||||
|
import net.corda.core.crypto.SignedData
|
||||||
|
import net.corda.core.crypto.sha256
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.crypto.*
|
import net.corda.core.crypto.*
|
||||||
import net.corda.core.internal.cert
|
import net.corda.core.internal.cert
|
||||||
import net.corda.core.internal.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
|
import net.corda.core.serialization.SerializedBytes
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
@ -16,7 +22,6 @@ import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
|||||||
import net.corda.nodeapi.internal.crypto.CertificateType
|
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||||
import net.corda.testing.ROOT_CA
|
import net.corda.testing.ROOT_CA
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.eclipse.jetty.server.Server
|
import org.eclipse.jetty.server.Server
|
||||||
import org.eclipse.jetty.server.ServerConnector
|
import org.eclipse.jetty.server.ServerConnector
|
||||||
import org.eclipse.jetty.server.handler.HandlerCollection
|
import org.eclipse.jetty.server.handler.HandlerCollection
|
||||||
@ -37,10 +42,10 @@ import javax.ws.rs.core.Response.ok
|
|||||||
class NetworkMapServer(cacheTimeout: Duration,
|
class NetworkMapServer(cacheTimeout: Duration,
|
||||||
hostAndPort: NetworkHostAndPort,
|
hostAndPort: NetworkHostAndPort,
|
||||||
root_ca: CertificateAndKeyPair = ROOT_CA, // Default to ROOT_CA for testing.
|
root_ca: CertificateAndKeyPair = ROOT_CA, // Default to ROOT_CA for testing.
|
||||||
|
private val myHostNameValue: String = "test.host.name",
|
||||||
vararg additionalServices: Any) : Closeable {
|
vararg additionalServices: Any) : Closeable {
|
||||||
companion object {
|
companion object {
|
||||||
val stubNetworkParameter = NetworkParameters(1, emptyList(), 10485760, 40000, Instant.now(), 10)
|
private val stubNetworkParameters = NetworkParameters(1, emptyList(), 10485760, 40000, Instant.now(), 10)
|
||||||
private val serializedParameters = stubNetworkParameter.serialize()
|
|
||||||
|
|
||||||
private fun networkMapKeyAndCert(rootCAKeyAndCert: CertificateAndKeyPair): CertificateAndKeyPair {
|
private fun networkMapKeyAndCert(rootCAKeyAndCert: CertificateAndKeyPair): CertificateAndKeyPair {
|
||||||
val networkMapKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val networkMapKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
@ -48,15 +53,25 @@ class NetworkMapServer(cacheTimeout: Duration,
|
|||||||
CertificateType.INTERMEDIATE_CA,
|
CertificateType.INTERMEDIATE_CA,
|
||||||
rootCAKeyAndCert.certificate,
|
rootCAKeyAndCert.certificate,
|
||||||
rootCAKeyAndCert.keyPair,
|
rootCAKeyAndCert.keyPair,
|
||||||
X500Name("CN=Corda Network Map,L=London"),
|
CordaX500Name("Corda Network Map", "R3 Ltd", "London","GB"),
|
||||||
networkMapKey.public).cert
|
networkMapKey.public).cert
|
||||||
|
// Check that the certificate validates. Nodes will perform this check upon receiving a network map,
|
||||||
|
// it's better to fail here than there.
|
||||||
|
X509Utilities.validateCertificateChain(rootCAKeyAndCert.certificate.cert, networkMapCert)
|
||||||
return CertificateAndKeyPair(networkMapCert.toX509CertHolder(), networkMapKey)
|
return CertificateAndKeyPair(networkMapCert.toX509CertHolder(), networkMapKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val server: Server
|
private val server: Server
|
||||||
|
var networkParameters: NetworkParameters = stubNetworkParameters
|
||||||
|
set(networkParameters) {
|
||||||
|
check(field == stubNetworkParameters) { "Network parameters can be set only once" }
|
||||||
|
field = networkParameters
|
||||||
|
}
|
||||||
|
private val serializedParameters get() = networkParameters.serialize()
|
||||||
private val service = InMemoryNetworkMapService(cacheTimeout, networkMapKeyAndCert(root_ca))
|
private val service = InMemoryNetworkMapService(cacheTimeout, networkMapKeyAndCert(root_ca))
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
server = Server(InetSocketAddress(hostAndPort.host, hostAndPort.port)).apply {
|
server = Server(InetSocketAddress(hostAndPort.host, hostAndPort.port)).apply {
|
||||||
handler = HandlerCollection().apply {
|
handler = HandlerCollection().apply {
|
||||||
@ -95,13 +110,13 @@ class NetworkMapServer(cacheTimeout: Duration,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Path("network-map")
|
@Path("network-map")
|
||||||
class InMemoryNetworkMapService(private val cacheTimeout: Duration, private val networkMapKeyAndCert: CertificateAndKeyPair) {
|
inner class InMemoryNetworkMapService(private val cacheTimeout: Duration,
|
||||||
|
private val networkMapKeyAndCert: CertificateAndKeyPair) {
|
||||||
private val nodeInfoMap = mutableMapOf<SecureHash, SignedNodeInfo>()
|
private val nodeInfoMap = mutableMapOf<SecureHash, SignedNodeInfo>()
|
||||||
private val parametersHash = serializedParameters.hash
|
private val parametersHash by lazy { serializedParameters.hash }
|
||||||
private val signedParameters = SignedData(
|
private val signedParameters by lazy { SignedData(
|
||||||
serializedParameters,
|
serializedParameters,
|
||||||
DigitalSignature.WithKey(networkMapKeyAndCert.keyPair.public, Crypto.doSign(networkMapKeyAndCert.keyPair.private, serializedParameters.bytes))
|
DigitalSignature.WithKey(networkMapKeyAndCert.keyPair.public, Crypto.doSign(networkMapKeyAndCert.keyPair.private, serializedParameters.bytes))) }
|
||||||
)
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("publish")
|
@Path("publish")
|
||||||
@ -151,7 +166,7 @@ class NetworkMapServer(cacheTimeout: Duration,
|
|||||||
@GET
|
@GET
|
||||||
@Path("my-hostname")
|
@Path("my-hostname")
|
||||||
fun getHostName(): Response {
|
fun getHostName(): Response {
|
||||||
return Response.ok("test.host.name").build()
|
return Response.ok(myHostNameValue).build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,8 @@ fun <A> verifierDriver(
|
|||||||
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
extraCordappPackagesToScan = extraCordappPackagesToScan,
|
||||||
notarySpecs = notarySpecs,
|
notarySpecs = notarySpecs,
|
||||||
jmxPolicy = jmxPolicy,
|
jmxPolicy = jmxPolicy,
|
||||||
compatibilityZone = null
|
compatibilityZone = null,
|
||||||
|
onNetworkParametersGeneration = { }
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
coerce = { it },
|
coerce = { it },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user