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:
Alberto Arri 2017-11-13 15:40:44 +00:00 committed by GitHub
parent 4c7dc58135
commit 523a6db0b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 224 additions and 20 deletions

4
.idea/compiler.xml generated
View File

@ -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" />

View 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.

View 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``

View File

@ -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}"

View 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

View File

@ -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(

View File

@ -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")

View File

@ -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")) {

View File

@ -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)
} }
} }
} }

View File

@ -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)
}

View File

@ -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()
} }

View File

@ -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)
}
}

View File

@ -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

View File

@ -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))
}
} }

View File

@ -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()

View File

@ -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