mirror of
https://github.com/corda/corda.git
synced 2024-12-19 04:57:58 +00:00
[CORDA-1445]: Raise proper error when starting node in devMode with compatibilityZoneURL. (#3109)
This commit is contained in:
parent
15e87050c7
commit
5e0b27cfae
@ -6,6 +6,8 @@ release, see :doc:`upgrade-notes`.
|
|||||||
|
|
||||||
Unreleased
|
Unreleased
|
||||||
==========
|
==========
|
||||||
|
* Node will now gracefully fail to start if ``devMode`` is true and ``compatibilityZoneURL`` is specified.
|
||||||
|
|
||||||
* Fixed an error thrown by NodeVaultService upon recording a transaction with a number of inputs greater than the default page size.
|
* 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``.
|
* Fixed incorrect computation of ``totalStates`` from ``otherResults`` in ``NodeVaultService``.
|
||||||
|
@ -1,23 +1,37 @@
|
|||||||
package net.corda.node.services.network
|
package net.corda.node.services.network
|
||||||
|
|
||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.internal.bufferUntilSubscribed
|
||||||
import net.corda.core.internal.concurrent.transpose
|
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.messaging.ParametersUpdateInfo
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
|
import net.corda.node.services.config.configureDevKeyAndTrustStores
|
||||||
|
import net.corda.nodeapi.internal.config.NodeSSLConfiguration
|
||||||
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.NETWORK_PARAMS_UPDATE_FILE_NAME
|
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_UPDATE_FILE_NAME
|
||||||
import net.corda.nodeapi.internal.network.SignedNetworkParameters
|
import net.corda.nodeapi.internal.network.SignedNetworkParameters
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
import net.corda.testing.core.*
|
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.driver.NodeHandle
|
import net.corda.testing.driver.NodeHandle
|
||||||
import net.corda.testing.driver.internal.NodeHandleInternal
|
import net.corda.testing.driver.internal.NodeHandleInternal
|
||||||
import net.corda.testing.driver.internal.RandomFree
|
import net.corda.testing.driver.internal.RandomFree
|
||||||
import net.corda.testing.node.internal.CompatibilityZoneParams
|
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.internalDriver
|
||||||
import net.corda.testing.node.internal.network.NetworkMapServer
|
import net.corda.testing.node.internal.network.NetworkMapServer
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
@ -63,7 +77,7 @@ class NetworkMapTest {
|
|||||||
initialiseSerialization = false,
|
initialiseSerialization = false,
|
||||||
notarySpecs = emptyList()
|
notarySpecs = emptyList()
|
||||||
) {
|
) {
|
||||||
val alice = startNode(providedName = ALICE_NAME).getOrThrow() as NodeHandleInternal
|
val alice = startNode(providedName = ALICE_NAME, devMode = false).getOrThrow() as NodeHandleInternal
|
||||||
val nextParams = networkMapServer.networkParameters.copy(epoch = 3, modifiedTime = Instant.ofEpochMilli(random63BitValue()))
|
val nextParams = networkMapServer.networkParameters.copy(epoch = 3, modifiedTime = Instant.ofEpochMilli(random63BitValue()))
|
||||||
val nextHash = nextParams.serialize().hash
|
val nextHash = nextParams.serialize().hash
|
||||||
val snapshot = alice.rpc.networkParametersFeed().snapshot
|
val snapshot = alice.rpc.networkParametersFeed().snapshot
|
||||||
@ -110,7 +124,7 @@ class NetworkMapTest {
|
|||||||
initialiseSerialization = false,
|
initialiseSerialization = false,
|
||||||
notarySpecs = emptyList()
|
notarySpecs = emptyList()
|
||||||
) {
|
) {
|
||||||
val alice = startNode(providedName = ALICE_NAME).getOrThrow()
|
val alice = startNode(providedName = ALICE_NAME, devMode = false).getOrThrow()
|
||||||
val networkParameters = (alice.baseDirectory / NETWORK_PARAMS_FILE_NAME)
|
val networkParameters = (alice.baseDirectory / NETWORK_PARAMS_FILE_NAME)
|
||||||
.readObject<SignedNetworkParameters>()
|
.readObject<SignedNetworkParameters>()
|
||||||
.verified()
|
.verified()
|
||||||
@ -125,17 +139,16 @@ class NetworkMapTest {
|
|||||||
internalDriver(
|
internalDriver(
|
||||||
portAllocation = portAllocation,
|
portAllocation = portAllocation,
|
||||||
compatibilityZone = compatibilityZone,
|
compatibilityZone = compatibilityZone,
|
||||||
initialiseSerialization = false
|
initialiseSerialization = false,
|
||||||
|
notarySpecs = emptyList()
|
||||||
) {
|
) {
|
||||||
val (aliceNode, bobNode, notaryNode) = listOf(
|
val (aliceNode, bobNode) = listOf(
|
||||||
startNode(providedName = ALICE_NAME),
|
startNode(providedName = ALICE_NAME, devMode = false),
|
||||||
startNode(providedName = BOB_NAME),
|
startNode(providedName = BOB_NAME, devMode = false)
|
||||||
defaultNotaryNode
|
|
||||||
).transpose().getOrThrow()
|
).transpose().getOrThrow()
|
||||||
|
|
||||||
notaryNode.onlySees(notaryNode.nodeInfo, aliceNode.nodeInfo, bobNode.nodeInfo)
|
aliceNode.onlySees(aliceNode.nodeInfo, bobNode.nodeInfo)
|
||||||
aliceNode.onlySees(notaryNode.nodeInfo, aliceNode.nodeInfo, bobNode.nodeInfo)
|
bobNode.onlySees(aliceNode.nodeInfo, bobNode.nodeInfo)
|
||||||
bobNode.onlySees(notaryNode.nodeInfo, aliceNode.nodeInfo, bobNode.nodeInfo)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,24 +157,20 @@ class NetworkMapTest {
|
|||||||
internalDriver(
|
internalDriver(
|
||||||
portAllocation = portAllocation,
|
portAllocation = portAllocation,
|
||||||
compatibilityZone = compatibilityZone,
|
compatibilityZone = compatibilityZone,
|
||||||
initialiseSerialization = false
|
initialiseSerialization = false,
|
||||||
|
notarySpecs = emptyList()
|
||||||
) {
|
) {
|
||||||
val (aliceNode, notaryNode) = listOf(
|
val aliceNode = startNode(providedName = ALICE_NAME, devMode = false).getOrThrow()
|
||||||
startNode(providedName = ALICE_NAME),
|
|
||||||
defaultNotaryNode
|
|
||||||
).transpose().getOrThrow()
|
|
||||||
|
|
||||||
notaryNode.onlySees(notaryNode.nodeInfo, aliceNode.nodeInfo)
|
aliceNode.onlySees(aliceNode.nodeInfo)
|
||||||
aliceNode.onlySees(notaryNode.nodeInfo, aliceNode.nodeInfo)
|
|
||||||
|
|
||||||
val bobNode = startNode(providedName = BOB_NAME).getOrThrow()
|
val bobNode = startNode(providedName = BOB_NAME, devMode = false).getOrThrow()
|
||||||
|
|
||||||
// Wait for network map client to poll for the next update.
|
// Wait for network map client to poll for the next update.
|
||||||
Thread.sleep(cacheTimeout.toMillis() * 2)
|
Thread.sleep(cacheTimeout.toMillis() * 2)
|
||||||
|
|
||||||
bobNode.onlySees(notaryNode.nodeInfo, aliceNode.nodeInfo, bobNode.nodeInfo)
|
bobNode.onlySees(aliceNode.nodeInfo, bobNode.nodeInfo)
|
||||||
notaryNode.onlySees(notaryNode.nodeInfo, aliceNode.nodeInfo, bobNode.nodeInfo)
|
aliceNode.onlySees(aliceNode.nodeInfo, bobNode.nodeInfo)
|
||||||
aliceNode.onlySees(notaryNode.nodeInfo, aliceNode.nodeInfo, bobNode.nodeInfo)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,25 +179,23 @@ class NetworkMapTest {
|
|||||||
internalDriver(
|
internalDriver(
|
||||||
portAllocation = portAllocation,
|
portAllocation = portAllocation,
|
||||||
compatibilityZone = compatibilityZone,
|
compatibilityZone = compatibilityZone,
|
||||||
initialiseSerialization = false
|
initialiseSerialization = false,
|
||||||
|
notarySpecs = emptyList()
|
||||||
) {
|
) {
|
||||||
val (aliceNode, bobNode, notaryNode) = listOf(
|
val (aliceNode, bobNode) = listOf(
|
||||||
startNode(providedName = ALICE_NAME),
|
startNode(providedName = ALICE_NAME, devMode = false),
|
||||||
startNode(providedName = BOB_NAME),
|
startNode(providedName = BOB_NAME, devMode = false)
|
||||||
defaultNotaryNode
|
|
||||||
).transpose().getOrThrow()
|
).transpose().getOrThrow()
|
||||||
|
|
||||||
notaryNode.onlySees(notaryNode.nodeInfo, aliceNode.nodeInfo, bobNode.nodeInfo)
|
aliceNode.onlySees(aliceNode.nodeInfo, bobNode.nodeInfo)
|
||||||
aliceNode.onlySees(notaryNode.nodeInfo, aliceNode.nodeInfo, bobNode.nodeInfo)
|
bobNode.onlySees(aliceNode.nodeInfo, bobNode.nodeInfo)
|
||||||
bobNode.onlySees(notaryNode.nodeInfo, aliceNode.nodeInfo, bobNode.nodeInfo)
|
|
||||||
|
|
||||||
networkMapServer.removeNodeInfo(aliceNode.nodeInfo)
|
networkMapServer.removeNodeInfo(aliceNode.nodeInfo)
|
||||||
|
|
||||||
// Wait for network map client to poll for the next update.
|
// Wait for network map client to poll for the next update.
|
||||||
Thread.sleep(cacheTimeout.toMillis() * 2)
|
Thread.sleep(cacheTimeout.toMillis() * 2)
|
||||||
|
|
||||||
notaryNode.onlySees(notaryNode.nodeInfo, bobNode.nodeInfo)
|
bobNode.onlySees(bobNode.nodeInfo)
|
||||||
bobNode.onlySees(notaryNode.nodeInfo, bobNode.nodeInfo)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,3 +208,19 @@ class NetworkMapTest {
|
|||||||
assertThat(rpc.networkMapSnapshot()).containsOnly(*nodes)
|
assertThat(rpc.networkMapSnapshot()).containsOnly(*nodes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun DriverDSLImpl.startNode(providedName: CordaX500Name, devMode: Boolean): CordaFuture<NodeHandle> {
|
||||||
|
var customOverrides = emptyMap<String, String>()
|
||||||
|
if (!devMode) {
|
||||||
|
val nodeDir = baseDirectory(providedName)
|
||||||
|
val nodeSslConfig = object : NodeSSLConfiguration {
|
||||||
|
override val baseDirectory = nodeDir
|
||||||
|
override val keyStorePassword = "cordacadevpass"
|
||||||
|
override val trustStorePassword = "trustpass"
|
||||||
|
override val crlCheckSoftFail = true
|
||||||
|
}
|
||||||
|
nodeSslConfig.configureDevKeyAndTrustStores(providedName)
|
||||||
|
customOverrides = mapOf("devMode" to "false")
|
||||||
|
}
|
||||||
|
return startNode(providedName = providedName, customOverrides = customOverrides)
|
||||||
|
}
|
||||||
|
@ -180,6 +180,7 @@ data class NodeConfigurationImpl(
|
|||||||
|
|
||||||
override fun validate(): List<String> {
|
override fun validate(): List<String> {
|
||||||
val errors = mutableListOf<String>()
|
val errors = mutableListOf<String>()
|
||||||
|
errors += validateDevModeOptions()
|
||||||
errors += validateRpcOptions(rpcOptions)
|
errors += validateRpcOptions(rpcOptions)
|
||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
@ -194,6 +195,16 @@ data class NodeConfigurationImpl(
|
|||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 errors
|
||||||
|
}
|
||||||
|
|
||||||
override val transactionCacheSizeBytes: Long
|
override val transactionCacheSizeBytes: Long
|
||||||
get() = transactionCacheSizeMegaBytes?.MB ?: super.transactionCacheSizeBytes
|
get() = transactionCacheSizeMegaBytes?.MB ?: super.transactionCacheSizeBytes
|
||||||
override val attachmentContentCacheSizeBytes: Long
|
override val attachmentContentCacheSizeBytes: Long
|
||||||
|
@ -6,8 +6,10 @@ import net.corda.core.utilities.seconds
|
|||||||
import net.corda.testing.core.ALICE_NAME
|
import net.corda.testing.core.ALICE_NAME
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||||
import net.corda.tools.shell.SSHDConfiguration
|
import net.corda.tools.shell.SSHDConfiguration
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import java.net.URI
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
@ -43,6 +45,15 @@ class NodeConfigurationImplTest {
|
|||||||
assertFalse { testConfiguration.copy(noLocalShell = true, sshd = null).shouldInitCrashShell() }
|
assertFalse { testConfiguration.copy(noLocalShell = true, sshd = null).shouldInitCrashShell() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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 errors = configuration.validate()
|
||||||
|
|
||||||
|
assertThat(errors).hasOnlyOneElementSatisfying { error -> error.contains("compatibilityZoneURL") && error.contains("devMode") }
|
||||||
|
}
|
||||||
|
|
||||||
private fun configDebugOptions(devMode: Boolean, devModeOptions: DevModeOptions?): NodeConfiguration {
|
private fun configDebugOptions(devMode: Boolean, devModeOptions: DevModeOptions?): NodeConfiguration {
|
||||||
return testConfiguration.copy(devMode = devMode, devModeOptions = devModeOptions)
|
return testConfiguration.copy(devMode = devMode, devModeOptions = devModeOptions)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user