Changing network parameters to use node info files instead of by hand… (#288)

* Changing network parameters to use node info files instead of by hand specification of notary

* Addressing review comments

* Different names for notaries

* Updating README
This commit is contained in:
Michal Kit 2018-01-05 15:10:34 +00:00 committed by GitHub
parent a639839a68
commit a83f4fd61b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 26 deletions

View File

@ -158,17 +158,19 @@ networkMapConfig {
### 3. Create notary node and register with the doorman
After the doorman service is started, start the notary node for the `initial-registration` process.
### 4. Add notary identities to the network parameters
The network parameters should contain the name and public key of the newly created notaries.
### 4. Generate node info files for notary nodes
Once notary nodes are registered, run the notary nodes with the `just-generate-node-info` flag.
This will generate the node info files, which then should be referenced in the network parameters configuration.
### 5. Add notary identities to the network parameters
The network parameters should contain reference to the notaries node info files.
Example network parameters file:
notaries : [{
name: "O=Notary A, L=Port Louis, C=MU, OU=Org Unit, CN=Service Name"
key: "GfHq2tTVk9z4eXgyWmExBB3JfHpeuYrk9jUc4zaVVSXpnW8FdCUNDhw6GRGN"
notaryNodeInfoFile: "/Path/To/NodeInfo/File1"
validating: true
}, {
name: "O=Notary B, L=Bali, C=ID, OU=Org Unit, CN=Service Name"
key: "GfHq2tTVk9z4eXgyEshv6vtBDjp7n76QZH5hk6VXLhk3vRTAmKcP9F9tRfPj"
notaryNodeInfoFile: "/Path/To/NodeInfo/File2"
validating: false
}]
minimumPlatformVersion = 1

View File

@ -1,10 +1,8 @@
notaries : [{
name: "O=Notary A, L=Port Louis, C=MU, OU=Org Unit, CN=Service Name"
key: "GfHq2tTVk9z4eXgyWmExBB3JfHpeuYrk9jUc4zaVVSXpnW8FdCUNDhw6GRGN"
notaryNodeInfoFile: "/Path/To/NodeInfo/File1"
validating: true
}, {
name: "O=Notary B, L=Bali, C=ID, OU=Org Unit, CN=Service Name"
key: "GfHq2tTVk9z4eXgyEshv6vtBDjp7n76QZH5hk6VXLhk3vRTAmKcP9F9tRfPj"
notaryNodeInfoFile: "/Path/To/NodeInfo/File2"
validating: false
}]
eventHorizonDays = 100

View File

@ -1,16 +1,21 @@
package com.r3.corda.networkmanage.doorman
import com.typesafe.config.Config
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.internal.readAll
import net.corda.core.serialization.deserialize
import net.corda.core.utilities.days
import net.corda.core.utilities.parsePublicKeyBase58
import net.corda.nodeapi.internal.SignedNodeInfo
import net.corda.nodeapi.internal.config.parseAs
import net.corda.nodeapi.internal.network.NetworkParameters
import net.corda.nodeapi.internal.network.NotaryInfo
import java.nio.file.Path
import java.nio.file.Paths
import java.time.Instant
/**
@ -20,14 +25,18 @@ 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 notaryNodeInfoFile path to the node info file of the notary node.
* @property validating whether the notary is validating
*/
internal data class NotaryConfiguration(private val name: CordaX500Name,
private val key: String,
internal data class NotaryConfiguration(private val notaryNodeInfoFile: Path,
private val validating: Boolean) {
fun toNotaryInfo(): NotaryInfo = NotaryInfo(Party(name, parsePublicKeyBase58(key)), validating)
fun toNotaryInfo(): NotaryInfo {
val nodeInfo = notaryNodeInfoFile.readAll().deserialize<SignedNodeInfo>().verified()
// It is always the last identity (in the list of identities) that corresponds to the notary identity.
// In case of a single notary, the list has only one element. In case of distributed notaries the list has
// two items and the second one corresponds to the notary identity.
return NotaryInfo(nodeInfo.legalIdentities.last(), validating)
}
}
/**
@ -50,14 +59,20 @@ internal data class NetworkParametersConfiguration(val minimumPlatformVersion: I
* a modifiedTime initialized with [Instant.now].
*/
fun parseNetworkParametersFrom(configFile: Path, epoch: Int = DEFAULT_EPOCH): NetworkParameters {
check(configFile.exists()) { "File $configFile does not exist" }
val networkParametersConfig = ConfigFactory.parseFile(configFile.toFile(), ConfigParseOptions.defaults())
.parseAs(NetworkParametersConfiguration::class)
return parseNetworkParameters(parseNetworkParametersConfigurationFrom(configFile), epoch)
}
return NetworkParameters(networkParametersConfig.minimumPlatformVersion,
networkParametersConfig.notaries.map { it.toNotaryInfo() },
networkParametersConfig.maxMessageSize,
networkParametersConfig.maxTransactionSize,
internal fun parseNetworkParametersConfigurationFrom(configFile: Path): NetworkParametersConfiguration {
check(configFile.exists()) { "File $configFile does not exist" }
return ConfigFactory.parseFile(configFile.toFile(), ConfigParseOptions.defaults())
.parseAs(NetworkParametersConfiguration::class)
}
internal fun parseNetworkParameters(configuration: NetworkParametersConfiguration, epoch: Int = DEFAULT_EPOCH): NetworkParameters {
return NetworkParameters(configuration.minimumPlatformVersion,
configuration.notaries.map { it.toNotaryInfo() },
configuration.maxMessageSize,
configuration.maxTransactionSize,
Instant.now(),
epoch)
}

View File

@ -1,21 +1,56 @@
package com.r3.corda.networkmanage
import com.r3.corda.networkmanage.doorman.NetworkParametersConfiguration
import com.r3.corda.networkmanage.doorman.NotaryConfiguration
import com.r3.corda.networkmanage.doorman.parseNetworkParameters
import com.r3.corda.networkmanage.doorman.parseNetworkParametersFrom
import net.corda.core.utilities.days
import com.typesafe.config.ConfigFactory
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.copyTo
import net.corda.core.internal.deleteIfExists
import net.corda.core.serialization.serialize
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.internal.createNodeInfoAndSigned
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.Rule
import org.junit.Test
import java.io.File
import org.junit.rules.TemporaryFolder
import java.nio.file.Path
import java.nio.file.Paths
import java.time.Instant
class NetworkParametersConfigurationTest {
private val validOverrideNetworkConfigPath = File("network-parameters.conf").toPath()
@Rule
@JvmField
val tempFolder = TemporaryFolder()
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
private fun generateNetworkParametersConfiguration() = NetworkParametersConfiguration(
notaries = listOf(
NotaryConfiguration(generateNodeInfoFile("Test1"), true),
NotaryConfiguration(generateNodeInfoFile("Test2"), false)
),
maxMessageSize = 100,
maxTransactionSize = 100,
minimumPlatformVersion = 1
)
private fun generateNodeInfoFile(organisation: String): Path {
val (_, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name(organisation, "Madrid", "ES"))
val path = tempFolder.newFile().toPath()
path.deleteIfExists()
signedNodeInfo.serialize().open().copyTo(path)
return path
}
@Test
fun `reads an existing file`() {
val networkParameters = parseNetworkParametersFrom(validOverrideNetworkConfigPath)
val networkParameters = parseNetworkParameters(generateNetworkParametersConfiguration())
assertThat(networkParameters.minimumPlatformVersion).isEqualTo(1)
val notaries = networkParameters.notaries
assertThat(notaries).hasSize(2)