CORDA-830 Introducing the network bootstrapper

Copying of the node-info files moved out of Cordform and into NetworkParametersGenerator (which is now called NetworkBootstrapper). This class becomes an external tool to enable deployment of nodes in a test setup on a single filesystem.
This commit is contained in:
Shams Asari
2017-12-07 14:48:31 +00:00
parent e9cead9055
commit 00a5e3db6b
33 changed files with 378 additions and 341 deletions

View File

@ -25,9 +25,9 @@ import net.corda.node.services.config.NotaryConfig
import net.corda.node.services.transactions.minClusterSize
import net.corda.node.services.transactions.minCorrectReplicas
import net.corda.nodeapi.internal.ServiceIdentityGenerator
import net.corda.nodeapi.internal.NotaryInfo
import net.corda.nodeapi.internal.network.NotaryInfo
import net.corda.testing.chooseIdentity
import net.corda.nodeapi.internal.NetworkParametersCopier
import net.corda.nodeapi.internal.network.NetworkParametersCopier
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand

View File

@ -1,19 +1,20 @@
package net.corda.node.services.network
import net.corda.core.crypto.SignedData
import net.corda.core.internal.list
import net.corda.core.internal.readAll
import net.corda.core.node.NodeInfo
import net.corda.core.serialization.deserialize
import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.seconds
import net.corda.nodeapi.internal.NETWORK_PARAMS_FILE_NAME
import net.corda.nodeapi.internal.NetworkParameters
import net.corda.testing.node.internal.CompatibilityZoneParams
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
import net.corda.nodeapi.internal.network.NetworkParameters
import net.corda.testing.ALICE_NAME
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.BOB_NAME
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.PortAllocation
import net.corda.testing.node.internal.CompatibilityZoneParams
import net.corda.testing.node.internal.internalDriver
import net.corda.testing.node.internal.network.NetworkMapServer
import org.assertj.core.api.Assertions.assertThat
@ -22,8 +23,6 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import java.net.URL
import java.nio.file.Files
import kotlin.streams.toList
import kotlin.test.assertEquals
class NetworkMapTest {
@ -51,10 +50,12 @@ class NetworkMapTest {
@Test
fun `node correctly downloads and saves network parameters file on startup`() {
internalDriver(portAllocation = portAllocation, compatibilityZone = compatibilityZone, initialiseSerialization = false) {
val aliceDir = baseDirectory(ALICE_NAME)
startNode(providedName = ALICE_NAME).getOrThrow()
val networkParameters = Files.list(aliceDir).toList().single { NETWORK_PARAMS_FILE_NAME == it.fileName.toString() }
.readAll().deserialize<SignedData<NetworkParameters>>().verified()
val alice = startNode(providedName = ALICE_NAME).getOrThrow()
val networkParameters = alice.configuration.baseDirectory
.list { paths -> paths.filter { it.fileName.toString() == NETWORK_PARAMS_FILE_NAME }.findFirst().get() }
.readAll()
.deserialize<SignedData<NetworkParameters>>()
.verified()
assertEquals(NetworkMapServer.stubNetworkParameter, networkParameters)
}
}

View File

@ -7,8 +7,8 @@ import net.corda.core.internal.createDirectories
import net.corda.core.internal.div
import net.corda.core.node.NodeInfo
import net.corda.core.node.services.KeyManagementService
import net.corda.nodeapi.internal.NodeInfoFilesCopier
import net.corda.nodeapi.internal.SignedNodeInfo
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier
import net.corda.testing.ALICE_NAME
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.internal.createNodeInfoAndSigned

View File

@ -59,10 +59,10 @@ import net.corda.node.services.vault.NodeVaultService
import net.corda.node.services.vault.VaultSoftLockManager
import net.corda.node.shell.InteractiveShell
import net.corda.node.utilities.AffinityExecutor
import net.corda.nodeapi.internal.NETWORK_PARAMS_FILE_NAME
import net.corda.nodeapi.internal.NetworkParameters
import net.corda.nodeapi.internal.SignedNodeInfo
import net.corda.nodeapi.internal.crypto.*
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
import net.corda.nodeapi.internal.network.NetworkParameters
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.nodeapi.internal.persistence.HibernateConfiguration
@ -73,7 +73,6 @@ import rx.Observable
import rx.Scheduler
import java.io.IOException
import java.lang.reflect.InvocationTargetException
import java.nio.file.Files
import java.security.KeyPair
import java.security.KeyStoreException
import java.security.PublicKey
@ -87,7 +86,6 @@ import java.util.concurrent.ExecutorService
import java.util.concurrent.TimeUnit.SECONDS
import kotlin.collections.set
import kotlin.reflect.KClass
import kotlin.streams.toList
import net.corda.core.crypto.generateKeyPair as cryptoGenerateKeyPair
/**
@ -210,10 +208,8 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
val schemaService = NodeSchemaService(cordappLoader.cordappSchemas)
val (identity, identityKeyPair) = obtainIdentity(notaryConfig = null)
val identityService = makeIdentityService(identity.certificate)
networkMapClient = configuration.compatibilityZoneURL?.let {
NetworkMapClient(it, identityService.trustRoot)
}
readNetworkParameters()
networkMapClient = configuration.compatibilityZoneURL?.let { NetworkMapClient(it, identityService.trustRoot) }
retrieveNetworkParameters()
// Do all of this in a database transaction so anything that might need a connection has one.
val (startedImpl, schedulerService) = initialiseDatabasePersistence(schemaService, identityService) { database ->
val networkMapCache = NetworkMapCacheImpl(PersistentNetworkMapCache(database, networkParameters.notaries), identityService)
@ -648,29 +644,31 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
return PersistentKeyManagementService(identityService, keyPairs)
}
private fun readNetworkParameters() {
val files = Files.list(configuration.baseDirectory).filter { NETWORK_PARAMS_FILE_NAME == it.fileName.toString() }.toList()
val paramsFromFile = try {
// It's fine at this point if we don't have network parameters or have corrupted file, later we check if parameters can be downloaded from network map server.
files[0].readAll().deserialize<SignedData<NetworkParameters>>().verified()
} catch (t: Exception) {
log.warn("Couldn't find correct network parameters file in the base directory")
null
private fun retrieveNetworkParameters() {
val networkParamsFile = configuration.baseDirectory.list { paths ->
paths.filter { it.fileName.toString() == NETWORK_PARAMS_FILE_NAME }.findFirst().orElse(null)
}
networkParameters = if (paramsFromFile != null) {
paramsFromFile
} else if (networkMapClient != null) {
log.info("Requesting network parameters from network map server...")
val (networkMap, _) = networkMapClient!!.getNetworkMap()
val signedParams = networkMapClient!!.getNetworkParameter(networkMap.networkParameterHash) ?: throw IllegalArgumentException("Failed loading network parameters from network map server")
val verifiedParams = signedParams.verified() // Verify before saving.
networkParameters = if (networkParamsFile != null) {
networkParamsFile.readAll().deserialize<SignedData<NetworkParameters>>().verified()
} else {
log.info("No network-parameters file found. Expecting network parameters to be available from the network map.")
val networkMapClient = checkNotNull(networkMapClient) {
"Node hasn't been configured to connect to a network map from which to get the network parameters"
}
val (networkMap, _) = networkMapClient.getNetworkMap()
val signedParams = checkNotNull(networkMapClient.getNetworkParameter(networkMap.networkParameterHash)) {
"Failed loading network parameters from network map server"
}
val verifiedParams = signedParams.verified()
signedParams.serialize().open().copyTo(configuration.baseDirectory / NETWORK_PARAMS_FILE_NAME)
verifiedParams
} else {
throw IllegalArgumentException("Couldn't load network parameters file")
}
log.info("Loaded network parameters $networkParameters")
check(networkParameters.minimumPlatformVersion <= versionInfo.platformVersion) { "Node's platform version is lower than network's required minimumPlatformVersion" }
log.info("Loaded network parameters: $networkParameters")
check(networkParameters.minimumPlatformVersion <= versionInfo.platformVersion) {
"Node's platform version is lower than network's required minimumPlatformVersion"
}
}
private fun makeCoreNotaryService(notaryConfig: NotaryConfig, database: CordaPersistence): NotaryService {

View File

@ -12,9 +12,9 @@ import net.corda.core.utilities.minutes
import net.corda.core.utilities.seconds
import net.corda.node.services.api.NetworkMapCacheInternal
import net.corda.node.utilities.NamedThreadFactory
import net.corda.nodeapi.internal.NetworkMap
import net.corda.nodeapi.internal.NetworkParameters
import net.corda.nodeapi.internal.SignedNetworkMap
import net.corda.nodeapi.internal.network.NetworkMap
import net.corda.nodeapi.internal.network.NetworkParameters
import net.corda.nodeapi.internal.network.SignedNetworkMap
import net.corda.nodeapi.internal.SignedNodeInfo
import okhttp3.CacheControl
import okhttp3.Headers

View File

@ -8,7 +8,7 @@ import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.seconds
import net.corda.nodeapi.internal.NodeInfoFilesCopier
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier
import net.corda.nodeapi.internal.SignedNodeInfo
import rx.Observable
import rx.Scheduler

View File

@ -25,7 +25,7 @@ import net.corda.node.services.api.NetworkMapCacheInternal
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.bufferUntilDatabaseCommit
import net.corda.nodeapi.internal.persistence.wrapWithDatabaseTransaction
import net.corda.nodeapi.internal.NotaryInfo
import net.corda.nodeapi.internal.network.NotaryInfo
import org.hibernate.Session
import rx.Observable
import rx.subjects.PublishSubject

View File

@ -7,17 +7,21 @@ import net.corda.core.utilities.getOrThrow
import net.corda.finance.DOLLARS
import net.corda.finance.flows.CashIssueFlow
import net.corda.node.services.config.NotaryConfig
import net.corda.nodeapi.internal.NetworkParameters
import net.corda.nodeapi.internal.NetworkParametersCopier
import net.corda.nodeapi.internal.NotaryInfo
import net.corda.testing.*
import net.corda.nodeapi.internal.network.NetworkParameters
import net.corda.nodeapi.internal.network.NetworkParametersCopier
import net.corda.nodeapi.internal.network.NotaryInfo
import net.corda.testing.ALICE_NAME
import net.corda.testing.BOB_NAME
import net.corda.testing.DUMMY_NOTARY_NAME
import net.corda.testing.chooseIdentity
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.node.*
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.After
import org.junit.Test
import java.nio.file.Path
import kotlin.test.assertFails
import org.assertj.core.api.Assertions.*
class NetworkParametersTest {
private val mockNet = MockNetwork(

View File

@ -16,8 +16,8 @@ import net.corda.core.node.NodeInfo
import net.corda.core.serialization.serialize
import net.corda.core.utilities.millis
import net.corda.node.services.api.NetworkMapCacheInternal
import net.corda.nodeapi.internal.NetworkMap
import net.corda.nodeapi.internal.SignedNodeInfo
import net.corda.nodeapi.internal.network.NetworkMap
import net.corda.testing.ALICE_NAME
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.internal.TestNodeInfoBuilder