mirror of
https://github.com/corda/corda.git
synced 2025-01-14 08:49:47 +00:00
ENT-990 Make doorman read an initial set of Network parameters from d… (#96)
ENT-990 Make doorman read an initial set of Network parameters from disk at start-up time
This commit is contained in:
parent
4c7dc58135
commit
523a6db0b9
4
.idea/compiler.xml
generated
4
.idea/compiler.xml
generated
@ -50,6 +50,8 @@
|
|||||||
<module name="graphs_test" target="1.8" />
|
<module name="graphs_test" target="1.8" />
|
||||||
<module name="intellij-plugin_main" target="1.8" />
|
<module name="intellij-plugin_main" target="1.8" />
|
||||||
<module name="intellij-plugin_test" target="1.8" />
|
<module name="intellij-plugin_test" target="1.8" />
|
||||||
|
<module name="irs-demo-cordapp_main" target="1.8" />
|
||||||
|
<module name="irs-demo-cordapp_test" target="1.8" />
|
||||||
<module name="irs-demo_integrationTest" target="1.8" />
|
<module name="irs-demo_integrationTest" target="1.8" />
|
||||||
<module name="irs-demo_main" target="1.8" />
|
<module name="irs-demo_main" target="1.8" />
|
||||||
<module name="irs-demo_test" target="1.8" />
|
<module name="irs-demo_test" target="1.8" />
|
||||||
@ -96,6 +98,8 @@
|
|||||||
<module name="samples_test" target="1.8" />
|
<module name="samples_test" target="1.8" />
|
||||||
<module name="sandbox_main" target="1.8" />
|
<module name="sandbox_main" target="1.8" />
|
||||||
<module name="sandbox_test" target="1.8" />
|
<module name="sandbox_test" target="1.8" />
|
||||||
|
<module name="sgx-hsm-tool_main" target="1.8" />
|
||||||
|
<module name="sgx-hsm-tool_test" target="1.8" />
|
||||||
<module name="sgx-jvm_hsm-tool_main" target="1.8" />
|
<module name="sgx-jvm_hsm-tool_main" target="1.8" />
|
||||||
<module name="sgx-jvm_hsm-tool_test" target="1.8" />
|
<module name="sgx-jvm_hsm-tool_test" target="1.8" />
|
||||||
<module name="simm-valuation-demo_integrationTest" target="1.8" />
|
<module name="simm-valuation-demo_integrationTest" target="1.8" />
|
||||||
|
32
docs/source/running-doorman.rst
Normal file
32
docs/source/running-doorman.rst
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
Running a doorman service
|
||||||
|
=========================
|
||||||
|
|
||||||
|
|
||||||
|
See the Readme in under ``network-management`` for detailed building instructions.
|
||||||
|
|
||||||
|
|
||||||
|
Configuration file
|
||||||
|
------------------
|
||||||
|
At startup Doorman reads a configuration file, passed with ``--configFile`` on the command line.
|
||||||
|
|
||||||
|
This is an example of what a Doorman configuration file might look like:
|
||||||
|
.. literalinclude:: ../../network-management/doorman.conf
|
||||||
|
|
||||||
|
Invoke Doorman with ``-?`` for a full list of supported command-line arguments.
|
||||||
|
|
||||||
|
|
||||||
|
Bootstrapping the network parameters
|
||||||
|
------------------------------------
|
||||||
|
When Doorman is running it will serve the current network parameters. The first time Doorman is
|
||||||
|
started it will need to know the initial value for the network parameters.
|
||||||
|
|
||||||
|
The initial values for the network parameters can be specified with a file, like this:
|
||||||
|
.. literalinclude:: ../../network-management/initial-network-parameters.conf
|
||||||
|
|
||||||
|
And the location of that file can be specified with: ``--initialNetworkParameters``.
|
||||||
|
Note that when reading from file:
|
||||||
|
|
||||||
|
1. ``epoch`` will always be set to 1,
|
||||||
|
2. ``modifiedTime`` will be the Doorman startup time
|
||||||
|
|
||||||
|
``epoch`` will increase by one every time the network parameters are updated.
|
8
network-management/Readme.md
Normal file
8
network-management/Readme.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
The Doorman source code is located under `network-management/src`
|
||||||
|
|
||||||
|
To build a fat jar containing all the doorman code you can simply invoke
|
||||||
|
.. sourcecode:: bash
|
||||||
|
./gradlew network-management:buildDoormanJAR
|
||||||
|
|
||||||
|
The built file will appear in
|
||||||
|
``network-management/build/libs/doorman-<VERSION>-capsule.jar``
|
@ -1,7 +1,7 @@
|
|||||||
ext {
|
ext {
|
||||||
// We use Corda release artifact dependencies instead of project dependencies to make sure each doorman releases are
|
// We use Corda release artifact dependencies instead of project dependencies to make sure each doorman release is
|
||||||
// align with the corresponding Corda release.
|
// aligned with the corresponding Corda release.
|
||||||
corda_dependency_version = '2.0-20171017.135310-6'
|
corda_dependency_version = '2.0-20171104.000037-23'
|
||||||
}
|
}
|
||||||
|
|
||||||
version "$corda_dependency_version"
|
version "$corda_dependency_version"
|
||||||
@ -92,6 +92,7 @@ dependencies {
|
|||||||
compile "net.corda:corda-node-api:$corda_dependency_version"
|
compile "net.corda:corda-node-api:$corda_dependency_version"
|
||||||
testCompile "net.corda:corda-test-utils:$corda_dependency_version"
|
testCompile "net.corda:corda-test-utils:$corda_dependency_version"
|
||||||
testCompile "net.corda:corda-node-driver:$corda_dependency_version"
|
testCompile "net.corda:corda-node-driver:$corda_dependency_version"
|
||||||
|
testCompile "net.corda:corda-test-common:$corda_dependency_version"
|
||||||
|
|
||||||
// Log4J: logging framework (with SLF4J bindings)
|
// Log4J: logging framework (with SLF4J bindings)
|
||||||
compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
|
compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
|
||||||
|
12
network-management/initial-network-parameters.conf
Normal file
12
network-management/initial-network-parameters.conf
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
notaries : [{
|
||||||
|
name: "O=Notary A, L=Port Louis, C=MU, OU=Org Unit, CN=Service Name"
|
||||||
|
key: "GfHq2tTVk9z4eXgyWmExBB3JfHpeuYrk9jUc4zaVVSXpnW8FdCUNDhw6GRGN"
|
||||||
|
validating: true
|
||||||
|
}, {
|
||||||
|
name: "O=Notary B, L=Bali, C=ID, OU=Org Unit, CN=Service Name"
|
||||||
|
key: "GfHq2tTVk9z4eXgyEshv6vtBDjp7n76QZH5hk6VXLhk3vRTAmKcP9F9tRfPj"
|
||||||
|
validating: false
|
||||||
|
}]
|
||||||
|
minimumPlatformVersion = 1
|
||||||
|
maxMessageSize = 100
|
||||||
|
maxTransactionSize = 100
|
@ -20,6 +20,7 @@ import org.junit.rules.TemporaryFolder
|
|||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
|
|
||||||
class DoormanIntegrationTest {
|
class DoormanIntegrationTest {
|
||||||
@Rule
|
@Rule
|
||||||
@ -41,7 +42,7 @@ class DoormanIntegrationTest {
|
|||||||
val signer = Signer(intermediateCAKey, arrayOf(intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate()))
|
val signer = Signer(intermediateCAKey, arrayOf(intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate()))
|
||||||
|
|
||||||
//Start doorman server
|
//Start doorman server
|
||||||
val doorman = startDoorman(NetworkHostAndPort("localhost", 0), database, true, signer, null)
|
val doorman = startDoorman(NetworkHostAndPort("localhost", 0), database, true, testNetworkParameters(emptyList()), signer, null)
|
||||||
|
|
||||||
// Start Corda network registration.
|
// Start Corda network registration.
|
||||||
val config = testNodeConfiguration(
|
val config = testNodeConfiguration(
|
||||||
|
@ -24,6 +24,7 @@ import net.corda.node.utilities.registration.NetworkRegistrationHelper
|
|||||||
import net.corda.testing.ALICE
|
import net.corda.testing.ALICE
|
||||||
import net.corda.testing.BOB
|
import net.corda.testing.BOB
|
||||||
import net.corda.testing.CHARLIE
|
import net.corda.testing.CHARLIE
|
||||||
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
import net.corda.testing.testNodeConfiguration
|
import net.corda.testing.testNodeConfiguration
|
||||||
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
|
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
|
||||||
import org.h2.tools.Server
|
import org.h2.tools.Server
|
||||||
@ -90,7 +91,8 @@ class SigningServiceIntegrationTest {
|
|||||||
// Identity service not needed doorman, corda persistence is not very generic.
|
// Identity service not needed doorman, corda persistence is not very generic.
|
||||||
throw UnsupportedOperationException()
|
throw UnsupportedOperationException()
|
||||||
}, SchemaService())
|
}, SchemaService())
|
||||||
val doorman = startDoorman(NetworkHostAndPort(HOST, 0), database, approveAll = true)
|
val doorman = startDoorman(NetworkHostAndPort(HOST, 0), database, approveAll = true,
|
||||||
|
initialNetworkMapParameters = testNetworkParameters(emptyList()))
|
||||||
|
|
||||||
// Start Corda network registration.
|
// Start Corda network registration.
|
||||||
val config = testNodeConfiguration(
|
val config = testNodeConfiguration(
|
||||||
@ -137,7 +139,8 @@ class SigningServiceIntegrationTest {
|
|||||||
// Identity service not needed doorman, corda persistence is not very generic.
|
// Identity service not needed doorman, corda persistence is not very generic.
|
||||||
throw UnsupportedOperationException()
|
throw UnsupportedOperationException()
|
||||||
}, SchemaService())
|
}, SchemaService())
|
||||||
val doorman = startDoorman(NetworkHostAndPort(HOST, 0), database, approveAll = true)
|
val doorman = startDoorman(NetworkHostAndPort(HOST, 0), database, approveAll = true,
|
||||||
|
initialNetworkMapParameters = testNetworkParameters(emptyList()))
|
||||||
|
|
||||||
thread(start = true, isDaemon = true) {
|
thread(start = true, isDaemon = true) {
|
||||||
val h2ServerArgs = arrayOf("-tcpPort", H2_TCP_PORT, "-tcpAllowOthers")
|
val h2ServerArgs = arrayOf("-tcpPort", H2_TCP_PORT, "-tcpAllowOthers")
|
||||||
|
@ -22,7 +22,8 @@ data class DoormanParameters(val basedir: Path,
|
|||||||
val databaseProperties: Properties? = null,
|
val databaseProperties: Properties? = null,
|
||||||
val jiraConfig: JiraConfig? = null,
|
val jiraConfig: JiraConfig? = null,
|
||||||
val keystorePath: Path? = null, // basedir / "certificates" / "caKeystore.jks",
|
val keystorePath: Path? = null, // basedir / "certificates" / "caKeystore.jks",
|
||||||
val rootStorePath: Path? = null // basedir / "certificates" / "rootCAKeystore.jks"
|
val rootStorePath: Path? = null, // basedir / "certificates" / "rootCAKeystore.jks"
|
||||||
|
val initialNetworkParameters: Path
|
||||||
) {
|
) {
|
||||||
enum class Mode {
|
enum class Mode {
|
||||||
DOORMAN, CA_KEYGEN, ROOT_KEYGEN
|
DOORMAN, CA_KEYGEN, ROOT_KEYGEN
|
||||||
@ -50,6 +51,7 @@ fun parseParameters(vararg args: String): DoormanParameters {
|
|||||||
accepts("rootPrivateKeyPassword", "Root private key password.").withRequiredArg().describedAs("password")
|
accepts("rootPrivateKeyPassword", "Root private key password.").withRequiredArg().describedAs("password")
|
||||||
accepts("host", "Doorman web service host override").withRequiredArg().describedAs("hostname")
|
accepts("host", "Doorman web service host override").withRequiredArg().describedAs("hostname")
|
||||||
accepts("port", "Doorman web service port override").withRequiredArg().ofType(Int::class.java).describedAs("port number")
|
accepts("port", "Doorman web service port override").withRequiredArg().ofType(Int::class.java).describedAs("port number")
|
||||||
|
accepts("initialNetworkParameters", "initial network parameters filepath").withRequiredArg().describedAs("The initial network map").describedAs("filepath")
|
||||||
}
|
}
|
||||||
|
|
||||||
val configFile = if (argConfig.hasPath("configFile")) {
|
val configFile = if (argConfig.hasPath("configFile")) {
|
||||||
|
@ -16,6 +16,7 @@ import com.r3.corda.networkmanage.doorman.webservice.RegistrationWebService
|
|||||||
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.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
|
import net.corda.core.node.NetworkParameters
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
@ -159,6 +160,7 @@ fun generateCAKeyPair(keystorePath: Path, rootStorePath: Path, rootKeystorePass:
|
|||||||
fun startDoorman(hostAndPort: NetworkHostAndPort,
|
fun startDoorman(hostAndPort: NetworkHostAndPort,
|
||||||
database: CordaPersistence,
|
database: CordaPersistence,
|
||||||
approveAll: Boolean,
|
approveAll: Boolean,
|
||||||
|
initialNetworkMapParameters: NetworkParameters,
|
||||||
signer: Signer? = null,
|
signer: Signer? = null,
|
||||||
jiraConfig: DoormanParameters.JiraConfig? = null): DoormanServer {
|
jiraConfig: DoormanParameters.JiraConfig? = null): DoormanServer {
|
||||||
|
|
||||||
@ -179,7 +181,8 @@ fun startDoorman(hostAndPort: NetworkHostAndPort,
|
|||||||
DefaultCsrHandler(requestService, signer)
|
DefaultCsrHandler(requestService, signer)
|
||||||
}
|
}
|
||||||
|
|
||||||
val doorman = DoormanServer(hostAndPort, RegistrationWebService(requestProcessor, DoormanServer.serverStatus), NodeInfoWebService(PersistenceNodeInfoStorage(database)))
|
val doorman = DoormanServer(hostAndPort, RegistrationWebService(requestProcessor, DoormanServer.serverStatus),
|
||||||
|
NodeInfoWebService(PersistenceNodeInfoStorage(database), initialNetworkMapParameters))
|
||||||
doorman.start()
|
doorman.start()
|
||||||
|
|
||||||
// Thread process approved request periodically.
|
// Thread process approved request periodically.
|
||||||
@ -241,7 +244,9 @@ fun main(args: Array<String>) {
|
|||||||
DoormanParameters.Mode.DOORMAN -> {
|
DoormanParameters.Mode.DOORMAN -> {
|
||||||
val database = configureDatabase(dataSourceProperties, databaseProperties, { throw UnsupportedOperationException() }, SchemaService())
|
val database = configureDatabase(dataSourceProperties, databaseProperties, { throw UnsupportedOperationException() }, SchemaService())
|
||||||
val signer = buildLocalSigner(this)
|
val signer = buildLocalSigner(this)
|
||||||
startDoorman(NetworkHostAndPort(host, port), database, approveAll, signer, jiraConfig)
|
|
||||||
|
val networkParameters = parseNetworkParametersFrom(initialNetworkParameters)
|
||||||
|
startDoorman(NetworkHostAndPort(host, port), database, approveAll, networkParameters, signer, jiraConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
package com.r3.corda.networkmanage.doorman
|
||||||
|
|
||||||
|
import com.typesafe.config.ConfigFactory
|
||||||
|
import com.typesafe.config.ConfigParseOptions
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.identity.Party
|
||||||
|
import net.corda.core.internal.exists
|
||||||
|
import net.corda.core.node.NetworkParameters
|
||||||
|
import net.corda.core.node.NotaryInfo
|
||||||
|
import net.corda.core.utilities.days
|
||||||
|
import net.corda.core.utilities.parsePublicKeyBase58
|
||||||
|
import net.corda.nodeapi.config.parseAs
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initial value for [NetworkParameters.epoch].
|
||||||
|
*/
|
||||||
|
private const val DEFAULT_EPOCH = 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data class representing a [NotaryInfo] which can be easily parsed by a typesafe [ConfigFactory].
|
||||||
|
* @property name the X500Name of the notary.
|
||||||
|
* @property key the public key as serialized by [toBase58String]
|
||||||
|
* @property validating whether the notary is validating
|
||||||
|
*/
|
||||||
|
internal data class NotaryConfiguration(private val name: CordaX500Name,
|
||||||
|
private val key: String,
|
||||||
|
private val validating: Boolean) {
|
||||||
|
fun toNotaryInfo(): NotaryInfo = NotaryInfo(Party(name, parsePublicKeyBase58(key)), validating)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* data class containing the fields from [NetworkParameters] which can be read at start-up time from doorman.
|
||||||
|
* It is a proper subset of [NetworkParameters] except for the [notaries] field which is replaced by a list of
|
||||||
|
* [NotaryConfiguration] which is parsable.
|
||||||
|
*
|
||||||
|
* This is public only because [parseAs] needs to be able to call its constructor.
|
||||||
|
*/
|
||||||
|
internal data class NetworkParametersConfiguration(val minimumPlatformVersion: Int,
|
||||||
|
val notaries: List<NotaryConfiguration>,
|
||||||
|
val eventHorizonDays: Int,
|
||||||
|
val maxMessageSize: Int,
|
||||||
|
val maxTransactionSize: Int)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a file and returns a [NetworkParameters] instance.
|
||||||
|
*
|
||||||
|
* @return a [NetworkParameters] with values read from [configFile] except:
|
||||||
|
* an epoch of [DEFAULT_EPOCH],
|
||||||
|
* an eventHorizon of [DEFAULT_EVENT_HORIZON], and
|
||||||
|
* a modifiedTime initialized with [Instant.now].
|
||||||
|
* If [configFile] is null [DEFAULT_NETWORK_PARAMETERS] is returned.
|
||||||
|
*/
|
||||||
|
fun parseNetworkParametersFrom(configFile: Path): NetworkParameters {
|
||||||
|
check(configFile.exists()) { "File $configFile does not exist" }
|
||||||
|
val initialNetworkParameters = ConfigFactory.parseFile(configFile.toFile(), ConfigParseOptions.defaults())
|
||||||
|
.parseAs(NetworkParametersConfiguration::class)
|
||||||
|
|
||||||
|
return NetworkParameters(initialNetworkParameters.minimumPlatformVersion,
|
||||||
|
initialNetworkParameters.notaries.map { it.toNotaryInfo() },
|
||||||
|
initialNetworkParameters.eventHorizonDays.days,
|
||||||
|
initialNetworkParameters.maxMessageSize,
|
||||||
|
initialNetworkParameters.maxTransactionSize,
|
||||||
|
Instant.now(),
|
||||||
|
DEFAULT_EPOCH)
|
||||||
|
}
|
@ -4,6 +4,7 @@ import com.r3.corda.networkmanage.common.persistence.NodeInfoStorage
|
|||||||
import com.r3.corda.networkmanage.doorman.webservice.NodeInfoWebService.Companion.networkMapPath
|
import com.r3.corda.networkmanage.doorman.webservice.NodeInfoWebService.Companion.networkMapPath
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.crypto.SignedData
|
import net.corda.core.crypto.SignedData
|
||||||
|
import net.corda.core.node.NetworkParameters
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
@ -21,7 +22,7 @@ import javax.ws.rs.core.Response.ok
|
|||||||
import javax.ws.rs.core.Response.status
|
import javax.ws.rs.core.Response.status
|
||||||
|
|
||||||
@Path(networkMapPath)
|
@Path(networkMapPath)
|
||||||
class NodeInfoWebService(private val nodeInfoStorage: NodeInfoStorage) {
|
class NodeInfoWebService(private val nodeInfoStorage: NodeInfoStorage, private val networkParameters: NetworkParameters) {
|
||||||
companion object {
|
companion object {
|
||||||
const val networkMapPath = "network-map"
|
const val networkMapPath = "network-map"
|
||||||
}
|
}
|
||||||
@ -60,6 +61,7 @@ class NodeInfoWebService(private val nodeInfoStorage: NodeInfoStorage) {
|
|||||||
@GET
|
@GET
|
||||||
fun getNetworkMap(): Response {
|
fun getNetworkMap(): Response {
|
||||||
// TODO: Cache the response?
|
// TODO: Cache the response?
|
||||||
|
// TODO: Add the networkParamters to this returned response.
|
||||||
return ok(ObjectMapper().writeValueAsString(nodeInfoStorage.getNodeInfoHashes())).build()
|
return ok(ObjectMapper().writeValueAsString(nodeInfoStorage.getNodeInfoHashes())).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.r3.corda.networkmanage
|
||||||
|
|
||||||
|
import com.r3.corda.networkmanage.doorman.parseNetworkParametersFrom
|
||||||
|
import net.corda.core.utilities.days
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
|
import org.junit.Test
|
||||||
|
import java.io.File
|
||||||
|
import java.nio.file.Paths
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
class NetworkParametersConfigurationTest {
|
||||||
|
|
||||||
|
private val validInitialNetworkConfigPath = File(javaClass.getResource("/initial-network-parameters.conf").toURI())
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `reads an existing file`() {
|
||||||
|
val confFile = validInitialNetworkConfigPath.toPath()
|
||||||
|
|
||||||
|
val networkParameters = parseNetworkParametersFrom(confFile)
|
||||||
|
assertThat(networkParameters.minimumPlatformVersion).isEqualTo(1)
|
||||||
|
assertThat(networkParameters.eventHorizon).isEqualTo(100.days)
|
||||||
|
val notaries = networkParameters.notaries
|
||||||
|
assertThat(notaries).hasSize(2)
|
||||||
|
assertThat(notaries[0].validating).isTrue()
|
||||||
|
assertThat(notaries[1].validating).isFalse()
|
||||||
|
assertThat(networkParameters.maxMessageSize).isEqualTo(100)
|
||||||
|
assertThat(networkParameters.maxTransactionSize).isEqualTo(100)
|
||||||
|
// This is rather weak, though making this an exact test will require mocking a clock.
|
||||||
|
assertThat(networkParameters.modifiedTime).isBefore(Instant.now())
|
||||||
|
assertThat(networkParameters.epoch).isEqualTo(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `throws on a non-existing file`() {
|
||||||
|
assertThatThrownBy {
|
||||||
|
parseNetworkParametersFrom(Paths.get("notHere"))
|
||||||
|
}.isInstanceOf(IllegalStateException::class.java)
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,7 @@ import net.corda.node.utilities.CordaPersistence
|
|||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.node.utilities.X509Utilities
|
||||||
import net.corda.node.utilities.configureDatabase
|
import net.corda.node.utilities.configureDatabase
|
||||||
import net.corda.nodeapi.internal.serialization.*
|
import net.corda.nodeapi.internal.serialization.*
|
||||||
|
import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties
|
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
|
@ -9,23 +9,26 @@ import kotlin.test.assertFailsWith
|
|||||||
|
|
||||||
class DoormanParametersTest {
|
class DoormanParametersTest {
|
||||||
private val testDummyPath = ".${File.separator}testDummyPath.jks"
|
private val testDummyPath = ".${File.separator}testDummyPath.jks"
|
||||||
|
private val validInitialNetworkConfigPath = File(javaClass.getResource("/initial-network-parameters.conf").toURI()).absolutePath
|
||||||
private val validConfigPath = File(javaClass.getResource("/doorman.conf").toURI()).absolutePath
|
private val validConfigPath = File(javaClass.getResource("/doorman.conf").toURI()).absolutePath
|
||||||
private val invalidConfigPath = File(javaClass.getResource("/doorman_fail.conf").toURI()).absolutePath
|
private val invalidConfigPath = File(javaClass.getResource("/doorman_fail.conf").toURI()).absolutePath
|
||||||
|
|
||||||
|
private val requiredArgs = arrayOf("--configFile", validConfigPath, "--initialNetworkParameters", validInitialNetworkConfigPath)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `parse mode flag arg correctly`() {
|
fun `parse mode flag arg correctly`() {
|
||||||
assertEquals(DoormanParameters.Mode.CA_KEYGEN, parseParameters("--mode", "CA_KEYGEN", "--configFile", validConfigPath).mode)
|
assertEquals(DoormanParameters.Mode.CA_KEYGEN, callParseParametersWithRequiredArgs("--mode", "CA_KEYGEN").mode)
|
||||||
assertEquals(DoormanParameters.Mode.ROOT_KEYGEN, parseParameters("--mode", "ROOT_KEYGEN", "--configFile", validConfigPath).mode)
|
assertEquals(DoormanParameters.Mode.ROOT_KEYGEN, callParseParametersWithRequiredArgs("--mode", "ROOT_KEYGEN").mode)
|
||||||
assertEquals(DoormanParameters.Mode.DOORMAN, parseParameters("--mode", "DOORMAN", "--configFile", validConfigPath).mode)
|
assertEquals(DoormanParameters.Mode.DOORMAN, callParseParametersWithRequiredArgs("--mode", "DOORMAN").mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `command line arg should override config file`() {
|
fun `command line arg should override config file`() {
|
||||||
val params = parseParameters("--keystorePath", testDummyPath, "--port", "1000", "--configFile", validConfigPath)
|
val params = callParseParametersWithRequiredArgs("--keystorePath", testDummyPath, "--port", "1000")
|
||||||
assertEquals(testDummyPath, params.keystorePath.toString())
|
assertEquals(testDummyPath, params.keystorePath.toString())
|
||||||
assertEquals(1000, params.port)
|
assertEquals(1000, params.port)
|
||||||
|
|
||||||
val params2 = parseParameters("--configFile", validConfigPath)
|
val params2 = callParseParametersWithRequiredArgs()
|
||||||
assertEquals(Paths.get("/opt/doorman/certificates/caKeystore.jks"), params2.keystorePath)
|
assertEquals(Paths.get("/opt/doorman/certificates/caKeystore.jks"), params2.keystorePath)
|
||||||
assertEquals(8080, params2.port)
|
assertEquals(8080, params2.port)
|
||||||
}
|
}
|
||||||
@ -40,11 +43,15 @@ class DoormanParametersTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `should parse jira config correctly`() {
|
fun `should parse jira config correctly`() {
|
||||||
val parameter = parseParameters("--configFile", validConfigPath)
|
val parameter = callParseParametersWithRequiredArgs()
|
||||||
assertEquals("https://doorman-jira-host.com/", parameter.jiraConfig?.address)
|
assertEquals("https://doorman-jira-host.com/", parameter.jiraConfig?.address)
|
||||||
assertEquals("TD", parameter.jiraConfig?.projectCode)
|
assertEquals("TD", parameter.jiraConfig?.projectCode)
|
||||||
assertEquals("username", parameter.jiraConfig?.username)
|
assertEquals("username", parameter.jiraConfig?.username)
|
||||||
assertEquals("password", parameter.jiraConfig?.password)
|
assertEquals("password", parameter.jiraConfig?.password)
|
||||||
assertEquals(41, parameter.jiraConfig?.doneTransitionCode)
|
assertEquals(41, parameter.jiraConfig?.doneTransitionCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun callParseParametersWithRequiredArgs(vararg additionalArgs: String): DoormanParameters {
|
||||||
|
return parseParameters(*(requiredArgs + additionalArgs))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ import net.corda.node.serialization.KryoServerSerializationScheme
|
|||||||
import net.corda.node.utilities.CertificateType
|
import net.corda.node.utilities.CertificateType
|
||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.node.utilities.X509Utilities
|
||||||
import net.corda.nodeapi.internal.serialization.*
|
import net.corda.nodeapi.internal.serialization.*
|
||||||
|
import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme
|
||||||
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.codehaus.jackson.map.ObjectMapper
|
import org.codehaus.jackson.map.ObjectMapper
|
||||||
import org.junit.BeforeClass
|
import org.junit.BeforeClass
|
||||||
@ -72,7 +74,8 @@ class NodeInfoWebServiceTest {
|
|||||||
on { getCertificatePath(any()) }.thenReturn(certPath)
|
on { getCertificatePath(any()) }.thenReturn(certPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
DoormanServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(nodeInfoStorage)).use {
|
DoormanServer(NetworkHostAndPort("localhost", 0),
|
||||||
|
NodeInfoWebService(nodeInfoStorage, testNetworkParameters(emptyList()))).use {
|
||||||
it.start()
|
it.start()
|
||||||
val registerURL = URL("http://${it.hostAndPort}/api/${NodeInfoWebService.networkMapPath}/register")
|
val registerURL = URL("http://${it.hostAndPort}/api/${NodeInfoWebService.networkMapPath}/register")
|
||||||
val nodeInfoAndSignature = SignedData(nodeInfo.serialize(), digitalSignature).serialize().bytes
|
val nodeInfoAndSignature = SignedData(nodeInfo.serialize(), digitalSignature).serialize().bytes
|
||||||
@ -98,7 +101,8 @@ class NodeInfoWebServiceTest {
|
|||||||
on { getCertificatePath(any()) }.thenReturn(certPath)
|
on { getCertificatePath(any()) }.thenReturn(certPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
DoormanServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(nodeInfoStorage)).use {
|
DoormanServer(NetworkHostAndPort("localhost", 0),
|
||||||
|
NodeInfoWebService(nodeInfoStorage, testNetworkParameters(emptyList()))).use {
|
||||||
it.start()
|
it.start()
|
||||||
val registerURL = URL("http://${it.hostAndPort}/api/${NodeInfoWebService.networkMapPath}/register")
|
val registerURL = URL("http://${it.hostAndPort}/api/${NodeInfoWebService.networkMapPath}/register")
|
||||||
val nodeInfoAndSignature = SignedData(nodeInfo.serialize(), digitalSignature).serialize().bytes
|
val nodeInfoAndSignature = SignedData(nodeInfo.serialize(), digitalSignature).serialize().bytes
|
||||||
@ -116,7 +120,8 @@ class NodeInfoWebServiceTest {
|
|||||||
val nodeInfoStorage: NodeInfoStorage = mock {
|
val nodeInfoStorage: NodeInfoStorage = mock {
|
||||||
on { getNodeInfoHashes() }.thenReturn(networkMapList)
|
on { getNodeInfoHashes() }.thenReturn(networkMapList)
|
||||||
}
|
}
|
||||||
DoormanServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(nodeInfoStorage)).use {
|
DoormanServer(NetworkHostAndPort("localhost", 0),
|
||||||
|
NodeInfoWebService(nodeInfoStorage, testNetworkParameters(emptyList()))).use {
|
||||||
it.start()
|
it.start()
|
||||||
val conn = URL("http://${it.hostAndPort}/api/${NodeInfoWebService.networkMapPath}").openConnection() as HttpURLConnection
|
val conn = URL("http://${it.hostAndPort}/api/${NodeInfoWebService.networkMapPath}").openConnection() as HttpURLConnection
|
||||||
val response = conn.inputStream.bufferedReader().use { it.readLine() }
|
val response = conn.inputStream.bufferedReader().use { it.readLine() }
|
||||||
@ -139,7 +144,8 @@ class NodeInfoWebServiceTest {
|
|||||||
on { getNodeInfo(nodeInfoHash) }.thenReturn(nodeInfo)
|
on { getNodeInfo(nodeInfoHash) }.thenReturn(nodeInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
DoormanServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(nodeInfoStorage)).use {
|
DoormanServer(NetworkHostAndPort("localhost", 0),
|
||||||
|
NodeInfoWebService(nodeInfoStorage, testNetworkParameters(emptyList()))).use {
|
||||||
it.start()
|
it.start()
|
||||||
val nodeInfoURL = URL("http://${it.hostAndPort}/api/${NodeInfoWebService.networkMapPath}/$nodeInfoHash")
|
val nodeInfoURL = URL("http://${it.hostAndPort}/api/${NodeInfoWebService.networkMapPath}/$nodeInfoHash")
|
||||||
val conn = nodeInfoURL.openConnection()
|
val conn = nodeInfoURL.openConnection()
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
notaries : [{
|
||||||
|
name: "O=Notary A, L=Port Louis, C=MU, OU=Org Unit, CN=Service Name"
|
||||||
|
key: "GfHq2tTVk9z4eXgyWmExBB3JfHpeuYrk9jUc4zaVVSXpnW8FdCUNDhw6GRGN"
|
||||||
|
validating: true
|
||||||
|
}, {
|
||||||
|
name: "O=Notary B, L=Bali, C=ID, OU=Org Unit, CN=Service Name"
|
||||||
|
key: "GfHq2tTVk9z4eXgyEshv6vtBDjp7n76QZH5hk6VXLhk3vRTAmKcP9F9tRfPj"
|
||||||
|
validating: false
|
||||||
|
}]
|
||||||
|
eventHorizonDays = 100
|
||||||
|
minimumPlatformVersion = 1
|
||||||
|
maxMessageSize = 100
|
||||||
|
maxTransactionSize = 100
|
Loading…
Reference in New Issue
Block a user