mirror of
https://github.com/corda/corda.git
synced 2025-01-31 08:25:50 +00:00
CORDA-1510 - Allow Doorman and NetworkMap to be configured independently (#3220)
* CORDA-1510 - Allow Doorman and NetworkMap to be configured independently Currently only one compatabilityZoneURL can be specified, however the two services can be run on as separate servers. Allow nodes to be configured in this manner * Partial review comments * Review comments * review comments
This commit is contained in:
parent
ee0d580448
commit
a3d88f752d
@ -7,6 +7,10 @@ release, see :doc:`upgrade-notes`.
|
||||
Unreleased
|
||||
==========
|
||||
|
||||
* Doorman and NetworkMap url's can now be configured individually rather than being assumed to be
|
||||
the same server. Current ``compatibilityZoneURL`` configurations remain valid. See both :doc:`corda-configuration-file`
|
||||
and :doc:`permissioning` for details.
|
||||
|
||||
* Improved audit trail for ``FinalityFlow`` and related sub-flows.
|
||||
|
||||
* ``NodeStartup`` will now only print node's configuration if ``devMode`` is ``true``, avoiding the risk of printing passwords in a production setup.
|
||||
@ -17,7 +21,7 @@ Unreleased
|
||||
public and was already internal for Kotlin code.
|
||||
|
||||
* RPC Framework moved from Kryo to the Corda AMQP implementation [Corda-847]. This completes the removal
|
||||
of ``Kryo`` from general use within Corda, remaining only for use in flow checkpointing.
|
||||
of ``Kryo`` from general use within Corda, remaining only for use in flow checkpointing.
|
||||
|
||||
* Set co.paralleluniverse.fibers.verifyInstrumentation=true in devMode.
|
||||
|
||||
|
@ -171,7 +171,16 @@ absolute path to the node's base directory.
|
||||
interfaces, and then by sending an IP discovery request to the network map service. Set to ``false`` to disable.
|
||||
|
||||
:compatibilityZoneURL: The root address of Corda compatibility zone network management services, it is used by the Corda node to register with the network and
|
||||
obtain Corda node certificate, (See :doc:`permissioning` for more information.) and also used by the node to obtain network map information.
|
||||
obtain Corda node certificate, (See :doc:`permissioning` for more information.) and also used by the node to obtain network map information. Cannot be
|
||||
set at the same time as the ``networkServices`` option.
|
||||
|
||||
:networkServices: If the Corda compatibility zone services, both network map and registration (doorman), are not running on the same endpoint
|
||||
and thus have different URLs then this option should be used in place of the ``compatibilityZoneURL`` setting.
|
||||
|
||||
:doormanURL: Root address of the network registration service.
|
||||
:networkMapURL: Root address of the network map service.
|
||||
|
||||
.. note:: Only one of ``compatibilityZoneURL`` or ``networkServices`` should be used.
|
||||
|
||||
:jvmArgs: An optional list of JVM args, as strings, which replace those inherited from the command line when launching via ``corda.jar``
|
||||
only. e.g. ``jvmArgs = [ "-Xmx220m", "-Xms220m", "-XX:+UseG1GC" ]``
|
||||
@ -236,7 +245,7 @@ Simple notary configuration file:
|
||||
notary : {
|
||||
validating : false
|
||||
}
|
||||
devMode : true
|
||||
devMode : false
|
||||
compatibilityZoneURL : "https://cz.corda.net"
|
||||
|
||||
An example ``web-server.conf`` file is as follow:
|
||||
@ -255,6 +264,10 @@ An example ``web-server.conf`` file is as follow:
|
||||
webAddress : "localhost:12347",
|
||||
rpcUsers : [{ username=user1, password=letmein, permissions=[ StartFlow.net.corda.protocols.CashProtocol ] }]
|
||||
|
||||
Configuring a node where the Corda Comatability Zone's registration and Network Map services exist on different URLs
|
||||
|
||||
.. literalinclude:: example-code/src/main/resources/example-node-with-networkservices.conf
|
||||
|
||||
Fields
|
||||
------
|
||||
|
||||
@ -311,4 +324,4 @@ Example adding/overriding keyStore password when starting Corda node:
|
||||
|
||||
.. sourcecode:: shell
|
||||
|
||||
java -Dcorda.rpcSettings.ssl.keyStorePassword=mypassword -jar node.jar
|
||||
java -Dcorda.rpcSettings.ssl.keyStorePassword=mypassword -jar node.jar
|
||||
|
@ -0,0 +1,25 @@
|
||||
myLegalName : "O=Bank A,L=London,C=GB"
|
||||
keyStorePassword : "cordacadevpass"
|
||||
trustStorePassword : "trustpass"
|
||||
crlCheckSoftFail: true
|
||||
dataSourceProperties : {
|
||||
dataSourceClassName : org.h2.jdbcx.JdbcDataSource
|
||||
dataSource.url : "jdbc:h2:file:"${baseDirectory}"/persistence"
|
||||
dataSource.user : sa
|
||||
dataSource.password : ""
|
||||
}
|
||||
p2pAddress : "my-corda-node:10002"
|
||||
rpcSettings = {
|
||||
useSsl = false
|
||||
standAloneBroker = false
|
||||
address : "my-corda-node:10003"
|
||||
adminAddress : "my-corda-node:10004"
|
||||
}
|
||||
rpcUsers : [
|
||||
{ username=user1, password=letmein, permissions=[ StartFlow.net.corda.protocols.CashProtocol ] }
|
||||
]
|
||||
devMode : false
|
||||
networkServices : {
|
||||
doormanURL = "https://registration.corda.net"
|
||||
networkMapURL = "https://cz.corda.net"
|
||||
}
|
@ -196,21 +196,25 @@ This can be overridden with the additional ``--network-root-truststore`` flag.
|
||||
The certificate signing request will be created based on node information obtained from the node configuration.
|
||||
The following information from the node configuration file is needed to generate the request.
|
||||
|
||||
:myLegalName: Your company's legal name as an X.500 string. X.500 allows differentiation between entities with the same
|
||||
name as the legal name needs to be unique on the network. If another node has already been permissioned with this
|
||||
name then the permissioning server will automatically reject the request. The request will also be rejected if it
|
||||
violates legal name rules, see :ref:`node_naming` for more information.
|
||||
* **myLegalName** Your company's legal name as an X.500 string. X.500 allows differentiation between entities with the same
|
||||
name as the legal name needs to be unique on the network. If another node has already been permissioned with this
|
||||
name then the permissioning server will automatically reject the request. The request will also be rejected if it
|
||||
violates legal name rules, see :ref:`node_naming` for more information.
|
||||
|
||||
:emailAddress: e.g. "admin@company.com"
|
||||
* **emailAddress** e.g. "admin@company.com"
|
||||
|
||||
:devMode: must be set to false
|
||||
* **devMode** must be set to false
|
||||
|
||||
:compatibilityZoneURL: Corda compatibility zone network management service root URL.
|
||||
* **networkServices or compatibilityZoneURL** The Corda compatibility zone services must be configured. This must be either:
|
||||
|
||||
A new pair of private and public keys generated by the Corda node will be used to create the request.
|
||||
* **compatibilityZoneURL** The Corda compatibility zone network management service root URL.
|
||||
* **networkServices** Replaces the ``compatibilityZoneURL`` when the Doorman and Network Map services
|
||||
are configured to operate on different URL endpoints. The ``doorman`` entry is used for registration.
|
||||
|
||||
The utility will submit the request to the doorman server and poll for a result periodically to retrieve the certificates.
|
||||
Once the request has been approved and the certificates downloaded from the server, the node will create the keystore and trust store using the certificates and the generated private key.
|
||||
A new pair of private and public keys generated by the Corda node will be used to create the request.
|
||||
|
||||
The utility will submit the request to the doorman server and poll for a result periodically to retrieve the certificates.
|
||||
Once the request has been approved and the certificates downloaded from the server, the node will create the keystore and trust store using the certificates and the generated private key.
|
||||
|
||||
.. note:: You can exit the utility at any time if the approval process is taking longer than expected. The request process will resume on restart.
|
||||
|
||||
|
@ -4,12 +4,8 @@ import net.corda.cordform.CordformNode
|
||||
import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.crypto.random63BitValue
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.bufferUntilSubscribed
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.internal.concurrent.transpose
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.exists
|
||||
import net.corda.core.internal.list
|
||||
import net.corda.core.internal.readObject
|
||||
import net.corda.core.messaging.ParametersUpdateInfo
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.serialization.serialize
|
||||
@ -21,18 +17,11 @@ import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
|
||||
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_UPDATE_FILE_NAME
|
||||
import net.corda.nodeapi.internal.network.SignedNetworkParameters
|
||||
import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.core.ALICE_NAME
|
||||
import net.corda.testing.core.BOB_NAME
|
||||
import net.corda.testing.core.SerializationEnvironmentRule
|
||||
import net.corda.testing.core.expect
|
||||
import net.corda.testing.core.expectEvents
|
||||
import net.corda.testing.core.sequence
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.driver.NodeHandle
|
||||
import net.corda.testing.driver.internal.NodeHandleInternal
|
||||
import net.corda.testing.driver.internal.RandomFree
|
||||
import net.corda.testing.node.internal.CompatibilityZoneParams
|
||||
import net.corda.testing.node.internal.DriverDSLImpl
|
||||
import net.corda.testing.node.internal.internalDriver
|
||||
import net.corda.testing.node.internal.*
|
||||
import net.corda.testing.node.internal.network.NetworkMapServer
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
@ -41,10 +30,13 @@ import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
import java.net.URL
|
||||
import java.time.Instant
|
||||
|
||||
class NetworkMapTest {
|
||||
@RunWith(Parameterized::class)
|
||||
class NetworkMapTest(var initFunc: (URL, NetworkMapServer) -> CompatibilityZoneParams) {
|
||||
@Rule
|
||||
@JvmField
|
||||
val testSerialization = SerializationEnvironmentRule(true)
|
||||
@ -55,13 +47,37 @@ class NetworkMapTest {
|
||||
private lateinit var networkMapServer: NetworkMapServer
|
||||
private lateinit var compatibilityZone: CompatibilityZoneParams
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
fun runParams() = listOf(
|
||||
{ addr: URL, nms: NetworkMapServer ->
|
||||
SharedCompatibilityZoneParams(
|
||||
addr,
|
||||
publishNotaries = {
|
||||
nms.networkParameters = testNetworkParameters(it, modifiedTime = Instant.ofEpochMilli(random63BitValue()), epoch = 2)
|
||||
}
|
||||
)
|
||||
},
|
||||
{ addr: URL, nms: NetworkMapServer ->
|
||||
SplitCompatibilityZoneParams(
|
||||
doormanURL = URL("http://I/Don't/Exist"),
|
||||
networkMapURL = addr,
|
||||
publishNotaries = {
|
||||
nms.networkParameters = testNetworkParameters(it, modifiedTime = Instant.ofEpochMilli(random63BitValue()), epoch = 2)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
fun start() {
|
||||
networkMapServer = NetworkMapServer(cacheTimeout, portAllocation.nextHostAndPort())
|
||||
val address = networkMapServer.start()
|
||||
compatibilityZone = CompatibilityZoneParams(URL("http://$address"), publishNotaries = {
|
||||
networkMapServer.networkParameters = testNetworkParameters(it, modifiedTime = Instant.ofEpochMilli(random63BitValue()), epoch = 2)
|
||||
})
|
||||
compatibilityZone = initFunc(URL("http://$address"), networkMapServer)
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -21,6 +21,7 @@ import net.corda.testing.driver.PortAllocation
|
||||
import net.corda.testing.internal.DEV_ROOT_CA
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import net.corda.testing.node.internal.CompatibilityZoneParams
|
||||
import net.corda.testing.node.internal.SharedCompatibilityZoneParams
|
||||
import net.corda.testing.node.internal.internalDriver
|
||||
import net.corda.testing.node.internal.network.NetworkMapServer
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
@ -79,7 +80,7 @@ class NodeRegistrationTest {
|
||||
|
||||
@Test
|
||||
fun `node registration correct root cert`() {
|
||||
val compatibilityZone = CompatibilityZoneParams(
|
||||
val compatibilityZone = SharedCompatibilityZoneParams(
|
||||
URL("http://$serverHostAndPort"),
|
||||
publishNotaries = { server.networkParameters = testNetworkParameters(it) },
|
||||
rootCert = DEV_ROOT_CA.certificate)
|
||||
|
@ -120,11 +120,11 @@ data class CmdLineOptions(val baseDirectory: Path,
|
||||
if (devMode) mapOf("devMode" to this.devMode) else emptyMap<String, Any>())
|
||||
)
|
||||
return rawConfig to Try.on {
|
||||
rawConfig.parseAsNodeConfiguration(unknownConfigKeysPolicy::handle).also {
|
||||
rawConfig.parseAsNodeConfiguration(unknownConfigKeysPolicy::handle).also { config ->
|
||||
if (nodeRegistrationOption != null) {
|
||||
require(!it.devMode) { "registration cannot occur in devMode" }
|
||||
requireNotNull(it.compatibilityZoneURL) {
|
||||
"compatibilityZoneURL must be present in node configuration file in registration mode."
|
||||
require(!config.devMode) { "registration cannot occur in devMode" }
|
||||
require(config.compatibilityZoneURL != null || config.networkServices != null) {
|
||||
"compatibilityZoneURL or networkServices must be present in the node configuration file in registration mode."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
|
||||
val (identity, identityKeyPair) = obtainIdentity(notaryConfig = null)
|
||||
val identityService = makeIdentityService(identity.certificate)
|
||||
|
||||
networkMapClient = configuration.compatibilityZoneURL?.let { NetworkMapClient(it, identityService.trustRoot) }
|
||||
networkMapClient = configuration.networkServices?.let { NetworkMapClient(it.networkMapURL, identityService.trustRoot) }
|
||||
|
||||
val networkParameters = NetworkParametersReader(identityService.trustRoot, networkMapClient, configuration.baseDirectory).networkParameters
|
||||
check(networkParameters.minimumPlatformVersion <= versionInfo.platformVersion) {
|
||||
|
@ -208,7 +208,9 @@ open class NodeStartup(val args: Array<String>) {
|
||||
}
|
||||
|
||||
protected open fun registerWithNetwork(conf: NodeConfiguration, nodeRegistrationConfig: NodeRegistrationOption) {
|
||||
val compatibilityZoneURL = conf.compatibilityZoneURL!!
|
||||
val compatibilityZoneURL = conf.networkServices?.doormanURL ?: throw RuntimeException(
|
||||
"compatibilityZoneURL or networkServices must be configured!")
|
||||
|
||||
println()
|
||||
println("******************************************************************")
|
||||
println("* *")
|
||||
|
@ -36,6 +36,7 @@ interface NodeConfiguration : NodeSSLConfiguration {
|
||||
val devMode: Boolean
|
||||
val devModeOptions: DevModeOptions?
|
||||
val compatibilityZoneURL: URL?
|
||||
val networkServices: NetworkServicesConfig?
|
||||
val certificateChainCheckPolicies: List<CertChainPolicyConfig>
|
||||
val verifierType: VerifierType
|
||||
val p2pMessagingRetry: P2PMessagingRetryConfiguration
|
||||
@ -116,6 +117,25 @@ data class BFTSMaRtConfiguration(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used as an alternative to the older compatibilityZoneURL to allow the doorman and network map
|
||||
* services for a node to be configured as different URLs. Cannot be set at the same time as the
|
||||
* compatibilityZoneURL, and will be defaulted (if not set) to both point at the configured
|
||||
* compatibilityZoneURL.
|
||||
*
|
||||
* @property doormanURL The URL of the tls certificate signing service.
|
||||
* @property networkMapURL The URL of the Network Map service.
|
||||
* @property inferred Non user setting that indicates weather the Network Services configuration was
|
||||
* set explicitly ([inferred] == false) or weather they have been inferred via the compatibilityZoneURL parameter
|
||||
* ([inferred] == true) where both the network map and doorman are running on the same endpoint. Only one,
|
||||
* compatibilityZoneURL or networkServices, can be set at any one time.
|
||||
*/
|
||||
data class NetworkServicesConfig(
|
||||
val doormanURL: URL,
|
||||
val networkMapURL: URL,
|
||||
val inferred : Boolean = false
|
||||
)
|
||||
|
||||
/**
|
||||
* Currently only used for notarisation requests.
|
||||
*
|
||||
@ -141,6 +161,7 @@ data class NodeConfigurationImpl(
|
||||
override val crlCheckSoftFail: Boolean,
|
||||
override val dataSourceProperties: Properties,
|
||||
override val compatibilityZoneURL: URL? = null,
|
||||
override var networkServices: NetworkServicesConfig? = null,
|
||||
override val tlsCertCrlDistPoint: URL? = null,
|
||||
override val tlsCertCrlIssuer: String? = null,
|
||||
override val rpcUsers: List<User>,
|
||||
@ -185,6 +206,7 @@ data class NodeConfigurationImpl(
|
||||
explicitAddress != null -> {
|
||||
require(settings.address == null) { "Can't provide top-level rpcAddress and rpcSettings.address (they control the same property)." }
|
||||
logger.warn("Top-level declaration of property 'rpcAddress' is deprecated. Please use 'rpcSettings.address' instead.")
|
||||
|
||||
settings.copy(address = explicitAddress)
|
||||
}
|
||||
else -> {
|
||||
@ -217,6 +239,7 @@ data class NodeConfigurationImpl(
|
||||
errors += validateDevModeOptions()
|
||||
errors += validateRpcOptions(rpcOptions)
|
||||
errors += validateTlsCertCrlConfig()
|
||||
errors += validateNetworkServices()
|
||||
return errors
|
||||
}
|
||||
|
||||
@ -231,12 +254,28 @@ data class NodeConfigurationImpl(
|
||||
}
|
||||
|
||||
private fun validateDevModeOptions(): List<String> {
|
||||
val errors = mutableListOf<String>()
|
||||
if (devMode) {
|
||||
compatibilityZoneURL?.let {
|
||||
errors += "'compatibilityZoneURL': present. Property cannot be set when 'devMode' is true."
|
||||
return listOf("'compatibilityZoneURL': present. Property cannot be set when 'devMode' is true.")
|
||||
}
|
||||
|
||||
// if compatibiliZoneURL is set then it will be copied into the networkServices field and thus skipping
|
||||
// this check by returning above is fine.
|
||||
networkServices?.let {
|
||||
return listOf("'networkServices': present. Property cannot be set when 'devMode' is true.")
|
||||
}
|
||||
}
|
||||
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
private fun validateNetworkServices(): List<String> {
|
||||
val errors = mutableListOf<String>()
|
||||
|
||||
if (compatibilityZoneURL != null && networkServices != null && !(networkServices!!.inferred)) {
|
||||
errors += "Cannot configure both compatibilityZoneUrl and networkServices simultaneously"
|
||||
}
|
||||
|
||||
return errors
|
||||
}
|
||||
|
||||
@ -258,6 +297,10 @@ data class NodeConfigurationImpl(
|
||||
|Please contact the R3 team on the public slack to discuss your use case.
|
||||
""".trimMargin())
|
||||
}
|
||||
|
||||
if (compatibilityZoneURL != null && networkServices == null) {
|
||||
networkServices = NetworkServicesConfig(compatibilityZoneURL, compatibilityZoneURL, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,8 @@ import net.corda.tools.shell.SSHDConfiguration
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatCode
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import java.net.URI
|
||||
import java.net.URL
|
||||
@ -127,7 +129,9 @@ class NodeConfigurationImplTest {
|
||||
|
||||
@Test
|
||||
fun `validation has error when compatibilityZoneURL is present and devMode is true`() {
|
||||
val configuration = testConfiguration.copy(devMode = true, compatibilityZoneURL = URI.create("https://r3.com").toURL())
|
||||
val configuration = testConfiguration.copy(
|
||||
devMode = true,
|
||||
compatibilityZoneURL = URL("https://r3.com"))
|
||||
|
||||
val errors = configuration.validate()
|
||||
|
||||
@ -146,6 +150,33 @@ class NodeConfigurationImplTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validation has error when compatibilityZone is present and devMode is true`() {
|
||||
val configuration = testConfiguration.copy(devMode = true, networkServices = NetworkServicesConfig(
|
||||
URL("https://r3.com.doorman"),
|
||||
URL("https://r3.com/nm")))
|
||||
|
||||
val errors = configuration.validate()
|
||||
|
||||
assertThat(errors).hasOnlyOneElementSatisfying { error -> error.contains("networkServices") && error.contains("devMode") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validation has error when both compatibilityZoneURL and networkServices are configured`() {
|
||||
val configuration = testConfiguration.copy(
|
||||
devMode = false,
|
||||
compatibilityZoneURL = URL("https://r3.com"),
|
||||
networkServices = NetworkServicesConfig(
|
||||
URL("https://r3.com.doorman"),
|
||||
URL("https://r3.com/nm")))
|
||||
|
||||
val errors = configuration.validate()
|
||||
|
||||
assertThat(errors).hasOnlyOneElementSatisfying {
|
||||
error -> error.contains("Cannot configure both compatibilityZoneUrl and networkServices simultaneously")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `rpcAddress and rpcSettings_address are equivalent`() {
|
||||
var rawConfig = ConfigFactory.parseResources("working-config.conf", ConfigParseOptions.defaults().setAllowMissing(false))
|
||||
@ -155,6 +186,18 @@ class NodeConfigurationImplTest {
|
||||
assertThatCode { rawConfig.parseAsNodeConfiguration() }.doesNotThrowAnyException()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `compatiilityZoneURL populates NetworkServices`() {
|
||||
val compatibilityZoneURL = URI.create("https://r3.com").toURL()
|
||||
val configuration = testConfiguration.copy(
|
||||
devMode = false,
|
||||
compatibilityZoneURL = compatibilityZoneURL)
|
||||
|
||||
assertNotNull(configuration.networkServices)
|
||||
assertEquals(compatibilityZoneURL, configuration.networkServices!!.doormanURL)
|
||||
assertEquals(compatibilityZoneURL, configuration.networkServices!!.networkMapURL)
|
||||
}
|
||||
|
||||
private fun configDebugOptions(devMode: Boolean, devModeOptions: DevModeOptions?): NodeConfiguration {
|
||||
return testConfiguration.copy(devMode = devMode, devModeOptions = devModeOptions)
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import net.corda.core.utilities.contextLogger
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.millis
|
||||
import net.corda.node.NodeRegistrationOption
|
||||
import net.corda.node.internal.ConfigurationException
|
||||
import net.corda.node.internal.Node
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.node.services.Permissions
|
||||
@ -184,7 +185,7 @@ class DriverDSLImpl(
|
||||
|
||||
val registrationFuture = if (compatibilityZone?.rootCert != null) {
|
||||
// We don't need the network map to be available to be able to register the node
|
||||
startNodeRegistration(name, compatibilityZone.rootCert, compatibilityZone.url)
|
||||
startNodeRegistration(name, compatibilityZone.rootCert, compatibilityZone.doormanURL())
|
||||
} else {
|
||||
doneFuture(Unit)
|
||||
}
|
||||
@ -209,7 +210,15 @@ class DriverDSLImpl(
|
||||
val rpcAdminAddress = portAllocation.nextHostAndPort()
|
||||
val webAddress = portAllocation.nextHostAndPort()
|
||||
val users = rpcUsers.map { it.copy(permissions = it.permissions + DRIVER_REQUIRED_PERMISSIONS) }
|
||||
val czUrlConfig = if (compatibilityZone != null) mapOf("compatibilityZoneURL" to compatibilityZone.url.toString()) else emptyMap()
|
||||
val czUrlConfig = when (compatibilityZone) {
|
||||
null -> emptyMap()
|
||||
is SharedCompatibilityZoneParams ->
|
||||
mapOf("compatibilityZoneURL" to compatibilityZone.doormanURL().toString())
|
||||
is SplitCompatibilityZoneParams ->
|
||||
mapOf("networkServices.doormanURL" to compatibilityZone.doormanURL().toString(),
|
||||
"networkServices.networkMapURL" to compatibilityZone.networkMapURL().toString())
|
||||
}
|
||||
|
||||
val overrides = configOf(
|
||||
"myLegalName" to name.toString(),
|
||||
"p2pAddress" to p2pAddress.toString(),
|
||||
@ -412,7 +421,7 @@ class DriverDSLImpl(
|
||||
startNotaryIdentityGeneration()
|
||||
} else {
|
||||
// With a root cert specified we delegate generation of the notary identities to the CZ.
|
||||
startAllNotaryRegistrations(compatibilityZone.rootCert, compatibilityZone.url)
|
||||
startAllNotaryRegistrations(compatibilityZone.rootCert, compatibilityZone.doormanURL())
|
||||
}
|
||||
notaryInfosFuture.map { notaryInfos ->
|
||||
compatibilityZone.publishNotaries(notaryInfos)
|
||||
@ -502,7 +511,7 @@ class DriverDSLImpl(
|
||||
private fun startNotaries(localNetworkMap: LocalNetworkMap?, customOverrides: Map<String, Any?>): List<CordaFuture<List<NodeHandle>>> {
|
||||
return notarySpecs.map {
|
||||
when (it.cluster) {
|
||||
null -> startSingleNotary(it, localNetworkMap, customOverrides )
|
||||
null -> startSingleNotary(it, localNetworkMap, customOverrides)
|
||||
is ClusterSpec.Raft,
|
||||
// DummyCluster is used for testing the notary communication path, and it does not matter
|
||||
// which underlying consensus algorithm is used, so we just stick to Raft
|
||||
@ -870,7 +879,8 @@ class DriverDSLImpl(
|
||||
val index = stackTrace.indexOfLast { it.className == "net.corda.testing.driver.Driver" }
|
||||
// In this case we're dealing with the the RPCDriver or one of it's cousins which are internal and we don't care about them
|
||||
if (index == -1) return emptyList()
|
||||
val callerPackage = Class.forName(stackTrace[index + 1].className).`package` ?: throw IllegalStateException("Function instantiating driver must be defined in a package.")
|
||||
val callerPackage = Class.forName(stackTrace[index + 1].className).`package`
|
||||
?: throw IllegalStateException("Function instantiating driver must be defined in a package.")
|
||||
return listOf(callerPackage.name)
|
||||
}
|
||||
|
||||
@ -1057,15 +1067,49 @@ fun <DI : DriverDSL, D : InternalDriverDSL, A> genericDriver(
|
||||
|
||||
/**
|
||||
* Internal API to enable testing of the network map service and node registration process using the internal driver.
|
||||
* @property url The base CZ URL for registration and network map updates
|
||||
*
|
||||
* @property publishNotaries Hook for a network map server to capture the generated [NotaryInfo] objects needed for
|
||||
* creating the network parameters. This is needed as the network map server is expected to distribute it. The callback
|
||||
* will occur on a different thread to the driver-calling thread.
|
||||
* @property rootCert If specified then the nodes will register themselves with the doorman service using [url] and expect
|
||||
* the registration response to be rooted at this cert. If not specified then no registration is performed and the dev
|
||||
* root cert is used as normal.
|
||||
*
|
||||
* @see SharedCompatibilityZoneParams
|
||||
* @see SplitCompatibilityZoneParams
|
||||
*/
|
||||
data class CompatibilityZoneParams(val url: URL, val publishNotaries: (List<NotaryInfo>) -> Unit, val rootCert: X509Certificate? = null)
|
||||
sealed class CompatibilityZoneParams(
|
||||
val publishNotaries: (List<NotaryInfo>) -> Unit,
|
||||
val rootCert: X509Certificate? = null
|
||||
) {
|
||||
abstract fun networkMapURL(): URL
|
||||
abstract fun doormanURL(): URL
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent network management services, network map and doorman, running on the same URL
|
||||
*/
|
||||
class SharedCompatibilityZoneParams(
|
||||
private val url: URL,
|
||||
publishNotaries: (List<NotaryInfo>) -> Unit,
|
||||
rootCert: X509Certificate? = null
|
||||
) : CompatibilityZoneParams(publishNotaries, rootCert) {
|
||||
override fun doormanURL() = url
|
||||
override fun networkMapURL() = url
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent network management services, network map and doorman, running on different URLs
|
||||
*/
|
||||
class SplitCompatibilityZoneParams(
|
||||
private val doormanURL: URL,
|
||||
private val networkMapURL: URL,
|
||||
publishNotaries: (List<NotaryInfo>) -> Unit,
|
||||
rootCert: X509Certificate? = null
|
||||
) : CompatibilityZoneParams(publishNotaries, rootCert) {
|
||||
override fun doormanURL() = doormanURL
|
||||
override fun networkMapURL() = networkMapURL
|
||||
}
|
||||
|
||||
fun <A> internalDriver(
|
||||
isDebug: Boolean = DriverParameters().isDebug,
|
||||
|
@ -467,6 +467,7 @@ private fun mockNodeConfiguration(): NodeConfiguration {
|
||||
doReturn(null).whenever(it).jmxMonitoringHttpPort
|
||||
doReturn(true).whenever(it).devMode
|
||||
doReturn(null).whenever(it).compatibilityZoneURL
|
||||
doReturn(null).whenever(it).networkServices
|
||||
doReturn(VerifierType.InMemory).whenever(it).verifierType
|
||||
doReturn(P2PMessagingRetryConfiguration(5.seconds, 3, backoffBase = 1.0)).whenever(it).p2pMessagingRetry
|
||||
doReturn(5.seconds.toMillis()).whenever(it).additionalNodeInfoPollingFrequencyMsec
|
||||
|
Loading…
x
Reference in New Issue
Block a user