Merge pull request #839 from corda/tudor_merge_14_05_2018

Tudor merge 14 05 2018
This commit is contained in:
Tudor Malene 2018-05-15 09:52:39 +01:00 committed by GitHub
commit 274dead627
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 312 additions and 42 deletions

View File

@ -120,7 +120,9 @@ buildscript {
classpath "net.corda.plugins:quasar-utils:$gradle_plugins_version"
classpath "net.corda.plugins:cordformation:$gradle_plugins_version"
classpath "net.corda.plugins:cordapp:$gradle_plugins_version"
classpath "net.corda.plugins:api-scanner:$gradle_plugins_version"
//TODO Anthony- this should be changed back to $gradle_plugins_version when the api-scaner is fixed
// classpath "net.corda.plugins:api-scanner:$gradle_plugins_version"
classpath "net.corda.plugins:api-scanner:4.0.15"
classpath 'com.github.ben-manes:gradle-versions-plugin:0.15.0'
classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:${dokka_version}"

View File

@ -8,7 +8,7 @@
# Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
#
gradlePluginsVersion=4.0.15
gradlePluginsVersion=4.0.19
kotlinVersion=1.2.41
platformVersion=4
guavaVersion=21.0

View File

@ -55,6 +55,10 @@ object Emoji {
val CODE_FREE: String = codePointsString(0x1F193)
@JvmStatic
val CODE_SOON: String = codePointsString(0x1F51C)
@JvmStatic
val CODE_DEVELOPER: String = codePointsString(0x1F469, 0x200D, 0x1F4BB)
@JvmStatic
val CODE_WARNING_SIGN: String = codePointsString(0x26A0, 0xFE0F)
/**
@ -75,6 +79,8 @@ object Emoji {
val lightBulb: String get() = if (emojiMode.get() != null) "$CODE_LIGHTBULB " else ""
val free: String get() = if (emojiMode.get() != null) "$CODE_FREE " else ""
val soon: String get() = if (emojiMode.get() != null) "$CODE_SOON " else ""
val developer: String get() = if (emojiMode.get() != null) "$CODE_DEVELOPER " else ""
val warningSign: String get() = if (emojiMode.get() != null) "$CODE_WARNING_SIGN " else "!"
// These have old/non-emoji symbols with better platform support.
val greenTick: String get() = if (emojiMode.get() != null) "$CODE_GREEN_TICK " else ""

View File

@ -10,6 +10,12 @@ Unreleased
* Node will now gracefully fail to start if ``devMode`` is true and ``compatibilityZoneURL`` is specified.
* Added smart detection logic for the development mode setting and an option to override it from the command line.
* Fixed an error thrown by NodeVaultService upon recording a transaction with a number of inputs greater than the default page size.
* Fixed incorrect computation of ``totalStates`` from ``otherResults`` in ``NodeVaultService``.
* Changes to the JSON/YAML serialisation format from ``JacksonSupport``, which also applies to the node shell:
* ``Instant`` and ``Date`` objects are serialised as ISO-8601 formatted strings rather than timestamps

View File

@ -172,9 +172,12 @@ absolute path to the node's base directory.
:devMode: This flag sets the node to run in development mode. On startup, if the keystore ``<workspace>/certificates/sslkeystore.jks``
does not exist, a developer keystore will be used if ``devMode`` is true. The node will exit if ``devMode`` is false
and the keystore does not exist. ``devMode`` also turns on background checking of flow checkpoints to shake out any
bugs in the checkpointing process. Also, if ``devMode`` is true, Hibernate will try to automatically create the schema required by Corda
or update an existing schema in the SQL database; if ``devMode`` is false, Hibernate will simply validate an existing schema
failing on node start if this schema is either not present or not compatible.
bugs in the checkpointing process.
Also, if ``devMode`` is true, Hibernate will try to automatically create the schema required by Corda
or update an existing schema in the SQL database; if ``devMode`` is false, Hibernate will simply validate the existing schema,
failing on node start if the schema is either not present or not compatible.
If no value is specified in the node config file, the node will attempt to detect if it's running on a developer machine and set ``devMode=true`` in that case.
This value can be overridden from the command line using the ``--dev-mode`` option.
:detectPublicIp: This flag toggles the auto IP detection behaviour, it is enabled by default. On startup the node will
attempt to discover its externally visible IP address first by looking for any public addresses on its network

View File

@ -95,11 +95,12 @@ class NetworkParametersUpdateTest : IntegrationTest() {
compatibilityZone = compatibilityZone,
notarySpecs = emptyList(),
initialiseSerialization = false,
extraCordappPackagesToScan = listOf("net.corda.finance")
extraCordappPackagesToScan = listOf("net.corda.finance"),
notaryCustomOverrides = mapOf("devMode" to false)
) {
var (alice, bob) = listOf(
startNode(providedName = ALICE_NAME),
startNode(providedName = BOB_NAME)
startNode(providedName = ALICE_NAME, customOverrides = mapOf("devMode" to false)),
startNode(providedName = BOB_NAME, customOverrides = mapOf("devMode" to false))
).map { it.getOrThrow() as NodeHandleInternal }
// Make sure that stopping Bob doesn't remove him from the network map
@ -139,7 +140,7 @@ class NetworkParametersUpdateTest : IntegrationTest() {
applyNetworkParametersAndStart(NetworkParametersCmd.FlagDay)
alice.stop()
alice = startNode(providedName = ALICE_NAME).getOrThrow() as NodeHandleInternal
alice = startNode(providedName = ALICE_NAME, customOverrides = mapOf("devMode" to false)).getOrThrow() as NodeHandleInternal
// TODO It is also possible to check what version of parameters node runs by writing flow that reads that value from ServiceHub
val networkParameters = (alice.configuration.baseDirectory / NETWORK_PARAMS_FILE_NAME)

View File

@ -130,17 +130,18 @@ class NodeRegistrationTest : IntegrationTest() {
compatibilityZone = compatibilityZone,
initialiseSerialization = false,
notarySpecs = listOf(NotarySpec(notaryName)),
extraCordappPackagesToScan = listOf("net.corda.finance")
extraCordappPackagesToScan = listOf("net.corda.finance"),
notaryCustomOverrides = mapOf("devMode" to false)
) {
val (alice, notary) = listOf(
startNode(providedName = aliceName),
startNode(providedName = aliceName, customOverrides = mapOf("devMode" to false)),
defaultNotaryNode
).map { it.getOrThrow() as NodeHandleInternal }
alice.onlySeesFromNetworkMap(alice, notary)
notary.onlySeesFromNetworkMap(alice, notary)
val genevieve = startNode(providedName = genevieveName).getOrThrow() as NodeHandleInternal
val genevieve = startNode(providedName = genevieveName, customOverrides = mapOf("devMode" to false)).getOrThrow() as NodeHandleInternal
// Wait for the nodes to poll again
Thread.sleep(timeoutMillis * 2)

View File

@ -101,11 +101,12 @@ class NodeRegistrationTest : IntegrationTest() {
compatibilityZone = compatibilityZone,
initialiseSerialization = false,
notarySpecs = listOf(NotarySpec(notaryName)),
extraCordappPackagesToScan = listOf("net.corda.finance")
extraCordappPackagesToScan = listOf("net.corda.finance"),
notaryCustomOverrides = mapOf("devMode" to false)
) {
val (alice, genevieve) = listOf(
startNode(providedName = aliceName),
startNode(providedName = genevieveName)
startNode(providedName = aliceName, customOverrides = mapOf("devMode" to false)),
startNode(providedName = genevieveName, customOverrides = mapOf("devMode" to false))
).transpose().getOrThrow()
assertThat(registrationHandler.idsPolled).containsOnly(

View File

@ -57,6 +57,7 @@ class NodeArgsParser : AbstractArgsParser<CmdLineOptions>() {
.withRequiredArg()
.withValuesConvertedBy(object : EnumConverter<UnknownConfigKeysPolicy>(UnknownConfigKeysPolicy::class.java) {})
.defaultsTo(UnknownConfigKeysPolicy.FAIL)
private val devModeArg = optionParser.accepts("dev-mode", "Run the node in developer mode. Unsafe for production.")
private val isVersionArg = optionParser.accepts("version", "Print the version and exit")
private val justGenerateNodeInfoArg = optionParser.accepts("just-generate-node-info",
@ -80,6 +81,7 @@ class NodeArgsParser : AbstractArgsParser<CmdLineOptions>() {
val networkRootTrustStorePath = optionSet.valueOf(networkRootTrustStorePathArg)
val networkRootTrustStorePassword = optionSet.valueOf(networkRootTrustStorePasswordArg)
val unknownConfigKeysPolicy = optionSet.valueOf(unknownConfigKeysPolicy)
val devMode = optionSet.has(devModeArg)
val registrationConfig = if (isRegistration) {
requireNotNull(networkRootTrustStorePassword) { "Network root trust store password must be provided in registration mode using --network-root-truststore-password." }
@ -99,7 +101,8 @@ class NodeArgsParser : AbstractArgsParser<CmdLineOptions>() {
sshdServer,
justGenerateNodeInfo,
bootstrapRaftCluster,
unknownConfigKeysPolicy)
unknownConfigKeysPolicy,
devMode)
}
}
@ -115,12 +118,14 @@ data class CmdLineOptions(val baseDirectory: Path,
val sshdServer: Boolean,
val justGenerateNodeInfo: Boolean,
val bootstrapRaftCluster: Boolean,
val unknownConfigKeysPolicy: UnknownConfigKeysPolicy) {
val unknownConfigKeysPolicy: UnknownConfigKeysPolicy,
val devMode: Boolean) {
fun loadConfig(): NodeConfiguration {
val config = ConfigHelper.loadConfig(
baseDirectory,
configFile,
configOverrides = ConfigFactory.parseMap(mapOf("noLocalShell" to this.noLocalShell))
configOverrides = ConfigFactory.parseMap(mapOf("noLocalShell" to this.noLocalShell) +
if (devMode) mapOf("devMode" to this.devMode) else emptyMap<String, Any>())
).parseAsNodeConfiguration(unknownConfigKeysPolicy::handle)
if (nodeRegistrationOption != null) {
require(!config.devMode) { "registration cannot occur in devMode" }

View File

@ -23,6 +23,7 @@ import net.corda.core.flows.*
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.Emoji
import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.VisibleForTesting
import net.corda.core.internal.concurrent.map
@ -179,8 +180,10 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
private fun initCertificate() {
if (configuration.devMode) {
log.warn("Corda node is running in dev mode.")
log.warn("The Corda node is running in developer mode. This is not suitable for production usage.")
configuration.configureWithDevSSLCertificate()
} else {
log.info("The Corda node is running in production mode. If this is a developer environment you can set 'devMode=true' in the node.conf file.")
}
validateKeystore()
}
@ -205,6 +208,9 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
open fun start(): StartedNode<AbstractNode> {
check(started == null) { "Node has already been started" }
if (configuration.devMode) {
Emoji.renderIfSupported { Node.printWarning("This node is running in developer mode! ${Emoji.developer} This is not safe for production deployment.") }
}
log.info("Node starting up ...")
initCertificate()
initialiseJVMAgents()

View File

@ -13,6 +13,7 @@ package net.corda.node.internal
import com.codahale.metrics.JmxReporter
import net.corda.client.rpc.internal.serialization.kryo.KryoClientSerializationScheme
import net.corda.core.concurrent.CordaFuture
import net.corda.core.internal.Emoji
import net.corda.core.internal.concurrent.openFuture
import net.corda.core.internal.concurrent.thenMatch
import net.corda.core.internal.div
@ -85,6 +86,13 @@ open class Node(configuration: NodeConfiguration,
LoggerFactory.getLogger(loggerName).info(msg)
}
fun printWarning(message: String) {
Emoji.renderIfSupported {
println("${Emoji.warningSign} ATTENTION: ${message}")
}
staticLog.warn(message)
}
internal fun failStartUp(message: String): Nothing {
println(message)
println("Corda will now exit...")

View File

@ -46,6 +46,10 @@ object ConfigHelper {
val appConfig = ConfigFactory.parseFile(configFile.toFile(), parseOptions.setAllowMissing(allowMissingConfig))
val databaseConfig = ConfigFactory.parseResources(System.getProperty("custom.databaseProvider")+".conf", parseOptions.setAllowMissing(true))
// Detect the underlying OS. If mac or windows non-server then we assume we're running in devMode. Unless specified otherwise.
val smartDevMode = CordaSystemUtils.isOsMac() || (CordaSystemUtils.isOsWindows() && !CordaSystemUtils.getOsName().toLowerCase().contains("server"))
val devModeConfig = ConfigFactory.parseMap(mapOf("devMode" to smartDevMode))
val systemOverrides = systemProperties().cordaEntriesOnly()
val environmentOverrides = systemEnvironment().cordaEntriesOnly()
val finalConfig = configOverrides
@ -56,6 +60,7 @@ object ConfigHelper {
.withFallback(configOf("baseDirectory" to baseDirectory.toString()))
.withFallback(databaseConfig) //for database integration tests
.withFallback(appConfig)
.withFallback(devModeConfig) // this needs to be after the appConfig, so it doesn't override the configured devMode
.withFallback(defaultConfig)
.resolve()
@ -112,3 +117,15 @@ fun SSLConfiguration.configureDevKeyAndTrustStores(myLegalName: CordaX500Name) {
/** Parse a value to be database schema name friendly and removes the last part if it matches a port ("_" followed by at least 5 digits) */
fun parseToDbSchemaFriendlyName(value: String) =
value.replace(" ", "").replace("-", "_").replace(Regex("_\\d{5,}$"),"")
/** This is generally covered by commons-lang. */
object CordaSystemUtils {
const val OS_NAME = "os.name"
const val MAC_PREFIX = "Mac"
const val WIN_PREFIX = "Windows"
fun isOsMac() = getOsName().startsWith(MAC_PREFIX)
fun isOsWindows() = getOsName().startsWith(WIN_PREFIX)
fun getOsName() = System.getProperty(OS_NAME)
}

View File

@ -22,7 +22,6 @@ database = {
transactionIsolationLevel = "REPEATABLE_READ"
exportHibernateJMXStatistics = "false"
}
devMode = true
h2port = 0
useTestClock = false
verifierType = InMemory

View File

@ -53,7 +53,8 @@ class NodeArgsParserTest {
sshdServer = false,
justGenerateNodeInfo = false,
bootstrapRaftCluster = false,
unknownConfigKeysPolicy = UnknownConfigKeysPolicy.FAIL))
unknownConfigKeysPolicy = UnknownConfigKeysPolicy.FAIL,
devMode = false))
}
@Test

View File

@ -11,7 +11,10 @@
package net.corda.node.services.config
import com.zaxxer.hikari.HikariConfig
import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import net.corda.core.internal.div
import net.corda.core.internal.toPath
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.nodeapi.internal.persistence.CordaPersistence.DataSourceConfigTag
import net.corda.core.utilities.seconds
@ -86,6 +89,59 @@ class NodeConfigurationImplTest {
assertFalse { testConfiguration.copy(noLocalShell = true, sshd = null).shouldInitCrashShell() }
}
@Test
fun `Dev mode is autodetected correctly`() {
val os = System.getProperty("os.name")
setSystemOs("Windows 98")
assertTrue(getConfig("test-config-empty.conf").getBoolean("devMode"))
setSystemOs("Mac Sierra")
assertTrue(getConfig("test-config-empty.conf").getBoolean("devMode"))
setSystemOs("Windows server 2008")
assertFalse(getConfig("test-config-empty.conf").getBoolean("devMode"))
setSystemOs("Linux")
assertFalse(getConfig("test-config-empty.conf").getBoolean("devMode"))
setSystemOs(os)
}
private fun setSystemOs(os: String) {
System.setProperty("os.name", os)
}
@Test
fun `Dev mode is read from the config over the autodetect logic`() {
assertTrue(getConfig("test-config-DevMode.conf").getBoolean("devMode"))
assertFalse(getConfig("test-config-noDevMode.conf").getBoolean("devMode"))
}
@Test
fun `Dev mode is true if overriden`() {
assertTrue(getConfig("test-config-DevMode.conf", ConfigFactory.parseMap(mapOf("devMode" to true))).getBoolean("devMode"))
assertTrue(getConfig("test-config-noDevMode.conf", ConfigFactory.parseMap(mapOf("devMode" to true))).getBoolean("devMode"))
assertTrue(getConfig("test-config-empty.conf", ConfigFactory.parseMap(mapOf("devMode" to true))).getBoolean("devMode"))
}
@Test
fun `Dev mode is false if overriden`() {
assertFalse(getConfig("test-config-DevMode.conf", ConfigFactory.parseMap(mapOf("devMode" to false))).getBoolean("devMode"))
assertFalse(getConfig("test-config-noDevMode.conf", ConfigFactory.parseMap(mapOf("devMode" to false))).getBoolean("devMode"))
assertFalse(getConfig("test-config-empty.conf", ConfigFactory.parseMap(mapOf("devMode" to false))).getBoolean("devMode"))
}
private fun getConfig(cfgName: String, overrides: Config = ConfigFactory.empty()): Config {
val path = this::class.java.classLoader.getResource(cfgName).toPath()
val cfg = ConfigHelper.loadConfig(
baseDirectory = path.parent,
configFile = path,
configOverrides = overrides
)
return cfg
}
@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())

View File

@ -0,0 +1 @@
devMode=true

View File

@ -0,0 +1 @@
devMode=false

View File

@ -46,6 +46,7 @@ class BankOfCordaCordform : CordformDefinition() {
address("localhost:10003")
adminAddress("localhost:10004")
}
devMode(true)
}
node {
name(BOC_NAME)
@ -57,6 +58,7 @@ class BankOfCordaCordform : CordformDefinition() {
}
webPort(BOC_WEB_PORT)
rpcUsers(User("bankUser", "test", setOf(all())))
devMode(true)
}
node {
name(BIGCORP_NAME)
@ -67,6 +69,7 @@ class BankOfCordaCordform : CordformDefinition() {
}
webPort(10010)
rpcUsers(User("bigCorpUser", "test", setOf(all())))
devMode(true)
}
}

View File

@ -44,6 +44,7 @@ class BFTNotaryCordform : CordformDefinition() {
adminAddress("localhost:10103")
}
rpcUsers(notaryDemoUser)
devMode(true)
}
node {
name(BOB_NAME)
@ -52,6 +53,7 @@ class BFTNotaryCordform : CordformDefinition() {
address("localhost:10006")
adminAddress("localhost:10106")
}
devMode(true)
}
val clusterAddresses = (0 until clusterSize).map { NetworkHostAndPort("localhost", 11000 + it * 10) }
fun notaryNode(replicaId: Int, configure: CordformNode.() -> Unit) = node {
@ -65,6 +67,7 @@ class BFTNotaryCordform : CordformDefinition() {
address("localhost:10010")
adminAddress("localhost:10110")
}
devMode(true)
}
notaryNode(1) {
p2pPort(10013)
@ -72,6 +75,7 @@ class BFTNotaryCordform : CordformDefinition() {
address("localhost:10014")
adminAddress("localhost:10114")
}
devMode(true)
}
notaryNode(2) {
p2pPort(10017)
@ -79,6 +83,7 @@ class BFTNotaryCordform : CordformDefinition() {
address("localhost:10018")
adminAddress("localhost:10118")
}
devMode(true)
}
notaryNode(3) {
p2pPort(10021)
@ -86,6 +91,7 @@ class BFTNotaryCordform : CordformDefinition() {
address("localhost:10022")
adminAddress("localhost:10122")
}
devMode(true)
}
}

View File

@ -32,6 +32,7 @@ class CustomNotaryCordform : CordformDefinition() {
adminAddress("localhost:10103")
}
rpcUsers(notaryDemoUser)
devMode(true)
}
node {
name(BOB_NAME)
@ -40,6 +41,7 @@ class CustomNotaryCordform : CordformDefinition() {
address("localhost:10006")
adminAddress("localhost:10106")
}
devMode(true)
}
node {
name(DUMMY_NOTARY_NAME)
@ -49,6 +51,7 @@ class CustomNotaryCordform : CordformDefinition() {
adminAddress("localhost:10110")
}
notary(NotaryConfig(validating = true, custom = true))
devMode(true)
}
}

View File

@ -44,6 +44,7 @@ class RaftNotaryCordform : CordformDefinition() {
adminAddress("localhost:10103")
}
rpcUsers(notaryDemoUser)
devMode(true)
}
node {
name(BOB_NAME)
@ -52,12 +53,14 @@ class RaftNotaryCordform : CordformDefinition() {
address("localhost:10006")
adminAddress("localhost:10106")
}
devMode(true)
}
fun notaryNode(index: Int, nodePort: Int, clusterPort: Int? = null, configure: CordformNode.() -> Unit) = node {
name(notaryNames[index])
val clusterAddresses = if (clusterPort != null ) listOf(NetworkHostAndPort("localhost", clusterPort)) else emptyList()
notary(NotaryConfig(validating = true, raft = RaftConfig(NetworkHostAndPort("localhost", nodePort), clusterAddresses)))
configure()
devMode(true)
}
notaryNode(0, 10008) {
p2pPort(10009)
@ -65,6 +68,7 @@ class RaftNotaryCordform : CordformDefinition() {
address("localhost:10010")
adminAddress("localhost:10110")
}
devMode(true)
}
notaryNode(1, 10012, 10008) {
p2pPort(10013)
@ -72,6 +76,7 @@ class RaftNotaryCordform : CordformDefinition() {
address("localhost:10014")
adminAddress("localhost:10114")
}
devMode(true)
}
notaryNode(2, 10016, 10008) {
p2pPort(10017)
@ -79,6 +84,7 @@ class RaftNotaryCordform : CordformDefinition() {
address("localhost:10018")
adminAddress("localhost:10118")
}
devMode(true)
}
}

View File

@ -38,6 +38,7 @@ class SingleNotaryCordform : CordformDefinition() {
adminAddress("localhost:10103")
}
rpcUsers(notaryDemoUser)
devMode(true)
}
node {
name(BOB_NAME)
@ -46,6 +47,7 @@ class SingleNotaryCordform : CordformDefinition() {
address("localhost:10006")
adminAddress("localhost:10106")
}
devMode(true)
}
node {
name(DUMMY_NOTARY_NAME)
@ -55,6 +57,7 @@ class SingleNotaryCordform : CordformDefinition() {
adminAddress("localhost:10110")
}
notary(NotaryConfig(validating = true))
devMode(true)
}
}

View File

@ -176,7 +176,7 @@ data class NodeParameters(
*/
data class JmxPolicy(val startJmxHttpServer: Boolean = false,
val jmxHttpServerPortAllocation: PortAllocation? =
if (startJmxHttpServer) PortAllocation.Incremental(7005) else null)
if (startJmxHttpServer) PortAllocation.Incremental(7005) else null)
/**
* [driver] allows one to start up nodes like this:
@ -211,7 +211,8 @@ fun <A> driver(defaultParameters: DriverParameters = DriverParameters(), dsl: Dr
extraCordappPackagesToScan = defaultParameters.extraCordappPackagesToScan,
jmxPolicy = defaultParameters.jmxPolicy,
compatibilityZone = null,
networkParameters = defaultParameters.networkParameters
networkParameters = defaultParameters.networkParameters,
notaryCustomOverrides = defaultParameters.notaryCustomOverrides
),
coerce = { it },
dsl = dsl,
@ -243,6 +244,7 @@ fun <A> driver(defaultParameters: DriverParameters = DriverParameters(), dsl: Dr
* @property jmxPolicy Used to specify whether to expose JMX metrics via Jolokia HHTP/JSON.
* @property networkParameters The network parameters to be used by all the nodes. [NetworkParameters.notaries] must be
* empty as notaries are defined by [notarySpecs].
* @property notaryCustomOverrides Extra settings that need to be passed to the notary.
*/
@Suppress("unused")
data class DriverParameters(
@ -258,8 +260,70 @@ data class DriverParameters(
val notarySpecs: List<NotarySpec> = listOf(NotarySpec(DUMMY_NOTARY_NAME)),
val extraCordappPackagesToScan: List<String> = emptyList(),
val jmxPolicy: JmxPolicy = JmxPolicy(),
val networkParameters: NetworkParameters = testNetworkParameters(notaries = emptyList())
val networkParameters: NetworkParameters = testNetworkParameters(notaries = emptyList()),
val notaryCustomOverrides: Map<String, Any?> = emptyMap()
) {
constructor(
isDebug: Boolean,
driverDirectory: Path,
portAllocation: PortAllocation,
debugPortAllocation: PortAllocation,
systemProperties: Map<String, String>,
useTestClock: Boolean,
startNodesInProcess: Boolean,
waitForAllNodesToFinish: Boolean,
notarySpecs: List<NotarySpec>,
extraCordappPackagesToScan: List<String>,
jmxPolicy: JmxPolicy,
networkParameters: NetworkParameters
) : this(
isDebug,
driverDirectory,
portAllocation,
debugPortAllocation,
systemProperties,
useTestClock,
true,
startNodesInProcess,
waitForAllNodesToFinish,
notarySpecs,
extraCordappPackagesToScan,
jmxPolicy,
networkParameters,
emptyMap()
)
constructor(
isDebug: Boolean,
driverDirectory: Path,
portAllocation: PortAllocation,
debugPortAllocation: PortAllocation,
systemProperties: Map<String, String>,
useTestClock: Boolean,
initialiseSerialization: Boolean,
startNodesInProcess: Boolean,
waitForAllNodesToFinish: Boolean,
notarySpecs: List<NotarySpec>,
extraCordappPackagesToScan: List<String>,
jmxPolicy: JmxPolicy,
networkParameters: NetworkParameters
) : this(
isDebug,
driverDirectory,
portAllocation,
debugPortAllocation,
systemProperties,
useTestClock,
initialiseSerialization,
startNodesInProcess,
waitForAllNodesToFinish,
notarySpecs,
extraCordappPackagesToScan,
jmxPolicy,
networkParameters,
emptyMap()
)
fun withIsDebug(isDebug: Boolean): DriverParameters = copy(isDebug = isDebug)
fun withDriverDirectory(driverDirectory: Path): DriverParameters = copy(driverDirectory = driverDirectory)
fun withPortAllocation(portAllocation: PortAllocation): DriverParameters = copy(portAllocation = portAllocation)
@ -273,4 +337,66 @@ data class DriverParameters(
fun withExtraCordappPackagesToScan(extraCordappPackagesToScan: List<String>): DriverParameters = copy(extraCordappPackagesToScan = extraCordappPackagesToScan)
fun withJmxPolicy(jmxPolicy: JmxPolicy): DriverParameters = copy(jmxPolicy = jmxPolicy)
fun withNetworkParameters(networkParameters: NetworkParameters): DriverParameters = copy(networkParameters = networkParameters)
fun withNotaryCustomOverrides(notaryCustomOverrides: Map<String, Any?>): DriverParameters = copy(notaryCustomOverrides = notaryCustomOverrides)
fun copy(
isDebug: Boolean,
driverDirectory: Path,
portAllocation: PortAllocation,
debugPortAllocation: PortAllocation,
systemProperties: Map<String, String>,
useTestClock: Boolean,
startNodesInProcess: Boolean,
waitForAllNodesToFinish: Boolean,
notarySpecs: List<NotarySpec>,
extraCordappPackagesToScan: List<String>,
jmxPolicy: JmxPolicy,
networkParameters: NetworkParameters
) = this.copy(
isDebug,
driverDirectory,
portAllocation,
debugPortAllocation,
systemProperties,
useTestClock,
true,
startNodesInProcess,
waitForAllNodesToFinish,
notarySpecs,
extraCordappPackagesToScan,
jmxPolicy,
networkParameters,
emptyMap()
)
fun copy(
isDebug: Boolean,
driverDirectory: Path,
portAllocation: PortAllocation,
debugPortAllocation: PortAllocation,
systemProperties: Map<String, String>,
useTestClock: Boolean,
initialiseSerialization: Boolean,
startNodesInProcess: Boolean,
waitForAllNodesToFinish: Boolean,
notarySpecs: List<NotarySpec>,
extraCordappPackagesToScan: List<String>,
jmxPolicy: JmxPolicy,
networkParameters: NetworkParameters
) = this.copy(
isDebug,
driverDirectory,
portAllocation,
debugPortAllocation,
systemProperties,
useTestClock,
initialiseSerialization,
startNodesInProcess,
waitForAllNodesToFinish,
notarySpecs,
extraCordappPackagesToScan,
jmxPolicy,
networkParameters,
emptyMap()
)
}

View File

@ -100,7 +100,8 @@ class DriverDSLImpl(
val jmxPolicy: JmxPolicy,
val notarySpecs: List<NotarySpec>,
val compatibilityZone: CompatibilityZoneParams?,
val networkParameters: NetworkParameters
val networkParameters: NetworkParameters,
val notaryCustomOverrides: Map<String, Any?>
) : InternalDriverDSL {
private var _executorService: ScheduledExecutorService? = null
val executorService get() = _executorService!!
@ -224,18 +225,19 @@ class DriverDSLImpl(
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 overrides = configOf(
"myLegalName" to name.toString(),
"p2pAddress" to p2pAddress.toString(),
"rpcSettings.address" to rpcAddress.toString(),
"rpcSettings.adminAddress" to rpcAdminAddress.toString(),
"useTestClock" to useTestClock,
"rpcUsers" to if (users.isEmpty()) defaultRpcUserList else users.map { it.toConfig().root().unwrapped() },
"verifierType" to verifierType.name
) + czUrlConfig + customOverrides
val config = NodeConfig(ConfigHelper.loadConfig(
baseDirectory = baseDirectory(name),
allowMissingConfig = true,
configOverrides = configOf(
"myLegalName" to name.toString(),
"p2pAddress" to p2pAddress.toString(),
"rpcSettings.address" to rpcAddress.toString(),
"rpcSettings.adminAddress" to rpcAdminAddress.toString(),
"useTestClock" to useTestClock,
"rpcUsers" to if (users.isEmpty()) defaultRpcUserList else users.map { it.toConfig().root().unwrapped() },
"verifierType" to verifierType.name
) + czUrlConfig + customOverrides
configOverrides = if (overrides.hasPath("devMode")) overrides else overrides + mapOf("devMode" to true)
))
return startNodeInternal(config, webAddress, startInSameProcess, maximumHeapSize, localNetworkMap)
}
@ -432,7 +434,7 @@ class DriverDSLImpl(
networkMapAvailability = notaryInfosFuture.map { it.second }
_notaries = notaryInfosFuture.map { (notaryInfos, localNetworkMap) ->
val listOfFutureNodeHandles = startNotaries(localNetworkMap)
val listOfFutureNodeHandles = startNotaries(localNetworkMap, notaryCustomOverrides)
notaryInfos.zip(listOfFutureNodeHandles) { (identity, validating), nodeHandlesFuture ->
NotaryHandle(identity, validating, nodeHandlesFuture)
}
@ -508,10 +510,10 @@ class DriverDSLImpl(
return (0 until spec.cluster!!.clusterSize).map { spec.name.copy(organisation = "${spec.name.organisation}-$it") }
}
private fun startNotaries(localNetworkMap: LocalNetworkMap?): List<CordaFuture<List<NodeHandle>>> {
private fun startNotaries(localNetworkMap: LocalNetworkMap?, customOverrides: Map<String, Any?>): List<CordaFuture<List<NodeHandle>>> {
return notarySpecs.map {
when (it.cluster) {
null -> startSingleNotary(it, localNetworkMap)
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
@ -525,13 +527,13 @@ class DriverDSLImpl(
// generating the configs for the nodes, probably making use of Any.toConfig()
private fun NotaryConfig.toConfigMap(): Map<String, Any> = mapOf("notary" to toConfig().root().unwrapped())
private fun startSingleNotary(spec: NotarySpec, localNetworkMap: LocalNetworkMap?): CordaFuture<List<NodeHandle>> {
private fun startSingleNotary(spec: NotarySpec, localNetworkMap: LocalNetworkMap?, customOverrides: Map<String, Any?>): CordaFuture<List<NodeHandle>> {
return startRegisteredNode(
spec.name,
localNetworkMap,
spec.rpcUsers,
spec.verifierType,
customOverrides = NotaryConfig(spec.validating).toConfigMap()
customOverrides = NotaryConfig(spec.validating).toConfigMap() + customOverrides
).map { listOf(it) }
}
@ -1037,7 +1039,8 @@ fun <DI : DriverDSL, D : InternalDriverDSL, A> genericDriver(
jmxPolicy = defaultParameters.jmxPolicy,
notarySpecs = defaultParameters.notarySpecs,
compatibilityZone = null,
networkParameters = defaultParameters.networkParameters
networkParameters = defaultParameters.networkParameters,
notaryCustomOverrides = defaultParameters.notaryCustomOverrides
)
)
val shutdownHook = addShutdownHook(driverDsl::shutdown)
@ -1081,6 +1084,7 @@ fun <A> internalDriver(
jmxPolicy: JmxPolicy = DriverParameters().jmxPolicy,
networkParameters: NetworkParameters = DriverParameters().networkParameters,
compatibilityZone: CompatibilityZoneParams? = null,
notaryCustomOverrides: Map<String, Any?> = DriverParameters().notaryCustomOverrides,
dsl: DriverDSLImpl.() -> A
): A {
return genericDriver(
@ -1097,7 +1101,8 @@ fun <A> internalDriver(
extraCordappPackagesToScan = extraCordappPackagesToScan,
jmxPolicy = jmxPolicy,
compatibilityZone = compatibilityZone,
networkParameters = networkParameters
networkParameters = networkParameters,
notaryCustomOverrides = notaryCustomOverrides
),
coerce = { it },
dsl = dsl,

View File

@ -105,6 +105,7 @@ abstract class NodeBasedTest(private val cordappPackages: List<String> = emptyLi
"database" to mapOf("runMigration" to "true"),
"myLegalName" to legalName.toString(),
"p2pAddress" to p2pAddress,
"devMode" to true,
"rpcSettings.address" to localPort[1].toString(),
"rpcSettings.adminAddress" to localPort[2].toString(),
"rpcUsers" to rpcUsers.map { it.toConfig().root().unwrapped() }

View File

@ -126,6 +126,7 @@ fun <A> rpcDriver(
externalTrace: Trace? = null,
jmxPolicy: JmxPolicy = JmxPolicy(),
networkParameters: NetworkParameters = testNetworkParameters(notaries = emptyList()),
notaryCustomOverrides: Map<String, Any?> = emptyMap(),
dsl: RPCDriverDSL.() -> A
): A {
return genericDriver(
@ -143,7 +144,8 @@ fun <A> rpcDriver(
notarySpecs = notarySpecs,
jmxPolicy = jmxPolicy,
compatibilityZone = null,
networkParameters = networkParameters
networkParameters = networkParameters,
notaryCustomOverrides = notaryCustomOverrides
), externalTrace
),
coerce = { it },

View File

@ -48,6 +48,7 @@ class NodeConfigTest {
val nodeConfig = config.nodeConf()
.withValue("baseDirectory", ConfigValueFactory.fromAnyRef(baseDir.toString()))
.withFallback(ConfigFactory.parseResources("reference.conf"))
.withFallback(ConfigFactory.parseMap(mapOf("devMode" to true)))
.resolve()
val fullConfig = nodeConfig.parseAsNodeConfiguration()