Removing NetworkParametersGenerator as an interface

This commit is contained in:
Shams Asari 2017-12-04 15:39:42 +00:00
parent cb11379d98
commit 4a677815ef
4 changed files with 42 additions and 64 deletions

View File

@ -1,4 +1,4 @@
gradlePluginsVersion=3.0.1-NETWORKMAP gradlePluginsVersion=3.0.2-NETWORKMAP
kotlinVersion=1.1.60 kotlinVersion=1.1.60
platformVersion=2 platformVersion=2
guavaVersion=21.0 guavaVersion=21.0

View File

@ -1,15 +0,0 @@
package net.corda.cordform;
import java.nio.file.Path;
import java.util.List;
public interface NetworkParametersGenerator {
/**
* Run generation of network parameters for [Cordformation]. Nodes need to have already their own [NodeInfo] files in their
* base directories, these files will be used to extract notary identities.
*
* @param nodesDirs - nodes directories that will be used for network parameters generation. Network parameters
* file will be dropped into each directory on this list.
*/
void run(List<Path> nodesDirs);
}

View File

@ -3,7 +3,6 @@ package net.corda.plugins
import groovy.lang.Closure import groovy.lang.Closure
import net.corda.cordform.CordformDefinition import net.corda.cordform.CordformDefinition
import net.corda.cordform.CordformNode import net.corda.cordform.CordformNode
import net.corda.cordform.NetworkParametersGenerator
import org.apache.tools.ant.filters.FixCrLfFilter import org.apache.tools.ant.filters.FixCrLfFilter
import org.gradle.api.DefaultTask import org.gradle.api.DefaultTask
import org.gradle.api.GradleException import org.gradle.api.GradleException
@ -33,7 +32,6 @@ open class Cordform : DefaultTask() {
*/ */
@Suppress("MemberVisibilityCanPrivate") @Suppress("MemberVisibilityCanPrivate")
var definitionClass: String? = null var definitionClass: String? = null
private val networkParametersGenClass: String = "net.corda.nodeapi.internal.TestNetworkParametersGenerator"
private var directory = defaultDirectory private var directory = defaultDirectory
private val nodes = mutableListOf<Node>() private val nodes = mutableListOf<Node>()
@ -122,14 +120,11 @@ open class Cordform : DefaultTask() {
/** /**
* The parametersGenerator needn't be compiled until just before our build method, so we load it manually via sourceSets.main.runtimeClasspath. * The parametersGenerator needn't be compiled until just before our build method, so we load it manually via sourceSets.main.runtimeClasspath.
*/ */
private fun loadParametersGenerator(): NetworkParametersGenerator { private fun loadNetworkParamsGenClass(): Class<*> {
val plugin = project.convention.getPlugin(JavaPluginConvention::class.java) val plugin = project.convention.getPlugin(JavaPluginConvention::class.java)
val classpath = plugin.sourceSets.getByName(MAIN_SOURCE_SET_NAME).runtimeClasspath val classpath = plugin.sourceSets.getByName(MAIN_SOURCE_SET_NAME).runtimeClasspath
val urls = classpath.files.map { it.toURI().toURL() }.toTypedArray() val urls = classpath.files.map { it.toURI().toURL() }.toTypedArray()
return URLClassLoader(urls, NetworkParametersGenerator::class.java.classLoader) return URLClassLoader(urls, javaClass.classLoader).loadClass("net.corda.nodeapi.internal.NetworkParametersGenerator")
.loadClass(networkParametersGenClass)
.asSubclass(NetworkParametersGenerator::class.java)
.newInstance()
} }
/** /**
@ -171,8 +166,12 @@ open class Cordform : DefaultTask() {
private fun generateAndInstallNetworkParameters() { private fun generateAndInstallNetworkParameters() {
project.logger.info("Generating and installing network parameters") project.logger.info("Generating and installing network parameters")
val networkParamsGenerator = loadParametersGenerator() val networkParamsGenClass = loadNetworkParamsGenClass()
networkParamsGenerator.run(nodes.map { it.fullPath() }) val nodeDirs = nodes.map(Node::fullPath)
val networkParamsGenObject = networkParamsGenClass.newInstance()
val runMethod = networkParamsGenClass.getMethod("run", List::class.java).apply { isAccessible = true }
// Call NetworkParametersGenerator.run
runMethod.invoke(networkParamsGenObject, nodeDirs)
} }
private fun CordformDefinition.getMatchingCordapps(): List<File> { private fun CordformDefinition.getMatchingCordapps(): List<File> {

View File

@ -1,10 +1,8 @@
package net.corda.nodeapi.internal package net.corda.nodeapi.internal
import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigFactory
import net.corda.cordform.CordformNode
import net.corda.cordform.NetworkParametersGenerator
import net.corda.core.crypto.SignedData import net.corda.core.crypto.SignedData
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party
import net.corda.core.internal.div import net.corda.core.internal.div
import net.corda.core.internal.list import net.corda.core.internal.list
import net.corda.core.internal.readAll import net.corda.core.internal.readAll
@ -16,26 +14,30 @@ import net.corda.core.serialization.internal._contextSerializationEnv
import net.corda.core.utilities.ByteSequence import net.corda.core.utilities.ByteSequence
import net.corda.core.utilities.contextLogger import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.days import net.corda.core.utilities.days
import net.corda.nodeapi.internal.serialization.* import net.corda.nodeapi.internal.serialization.AMQP_P2P_CONTEXT
import net.corda.nodeapi.internal.serialization.KRYO_P2P_CONTEXT
import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme
import net.corda.nodeapi.internal.serialization.kryo.AbstractKryoSerializationScheme import net.corda.nodeapi.internal.serialization.kryo.AbstractKryoSerializationScheme
import net.corda.nodeapi.internal.serialization.kryo.KryoHeaderV0_1 import net.corda.nodeapi.internal.serialization.kryo.KryoHeaderV0_1
import java.nio.file.Path import java.nio.file.Path
import java.time.Instant import java.time.Instant
import kotlin.streams.toList
// This class is used by deployNodes task to generate NetworkParameters in [Cordformation]. /**
* This class is loaded by Cordform using reflection to generate the network parameters. It is assumed that Cordform has
* already asked each node to generate its node info file.
*/
@Suppress("UNUSED") @Suppress("UNUSED")
class TestNetworkParametersGenerator : NetworkParametersGenerator { class NetworkParametersGenerator {
companion object { companion object {
private val logger = contextLogger() private val logger = contextLogger()
} }
override fun run(nodesDirs: List<Path>) { fun run(nodesDirs: List<Path>) {
logger.info("NetworkParameters generation using node directories: $nodesDirs") logger.info("NetworkParameters generation using node directories: $nodesDirs")
try { try {
initialiseSerialization() initialiseSerialization()
val notaryInfos = loadAndGatherNotaryIdentities(nodesDirs) val notaryInfos = gatherNotaryIdentities(nodesDirs)
val copier = NetworkParametersCopier(NetworkParameters( val copier = NetworkParametersCopier(NetworkParameters(
minimumPlatformVersion = 1, minimumPlatformVersion = 1,
notaries = notaryInfos, notaries = notaryInfos,
@ -45,40 +47,34 @@ class TestNetworkParametersGenerator : NetworkParametersGenerator {
maxTransactionSize = 40000, maxTransactionSize = 40000,
epoch = 1 epoch = 1
)) ))
nodesDirs.forEach { copier.install(it) } nodesDirs.forEach(copier::install)
} finally { } finally {
_contextSerializationEnv.set(null) _contextSerializationEnv.set(null)
} }
} }
private fun loadAndGatherNotaryIdentities(nodesDirs: List<Path>): List<NotaryInfo> { private fun gatherNotaryIdentities(nodesDirs: List<Path>): List<NotaryInfo> {
val infos = getAllNodeInfos(nodesDirs) return nodesDirs.mapNotNull { nodeDir ->
val configs = nodesDirs.map { ConfigFactory.parseFile((it / "node.conf").toFile()) } val nodeConfig = ConfigFactory.parseFile((nodeDir / "node.conf").toFile())
val notaryConfigs = configs.filter { it.hasPath("notary") } if (nodeConfig.hasPath("notary")) {
val notaries = notaryConfigs.associateBy( val validating = nodeConfig.getConfig("notary").getBoolean("validating")
{ CordaX500Name.parse(it.getString("myLegalName")) }, val nodeInfoFile = nodeDir.list { paths -> paths.filter { it.fileName.toString().startsWith("nodeInfo-") }.findFirst().get() }
{ it.getConfig("notary").getBoolean("validating") } processFile(nodeInfoFile)?.let { NotaryInfo(it.notaryIdentity(), validating) }
) } else {
// Now get the notary identities based on names passed from configs. There is one problem, for distributed notaries null
// in config we specify only node's main name, the notary identity isn't passed there. It's read from keystore on }
// node startup, so we have to look it up from node info as a second identity, which is ugly. }.distinct() // We need distinct as nodes part of a distributed notary share the same notary identity
return infos.mapNotNull {
info -> notaries[info.legalIdentities[0].name]?.let { NotaryInfo(info.notaryIdentity(), it) }
}.distinct()
} }
/** private fun NodeInfo.notaryIdentity(): Party {
* Loads latest NodeInfo files stored in node's base directory. return when (legalIdentities.size) {
* Scans main directory and [CordformNode.NODE_INFO_DIRECTORY]. // Single node notaries have just one identity like all other nodes. This identity is the notary identity
* Signatures are checked before returning a value. The latest value stored for a given name is returned. 1 -> legalIdentities[0]
* // Nodes which are part of a distributed notary have a second identity which is the composite identity of the
* @return list of latest [NodeInfo]s // cluster and is shared by all the other members. This is the notary identity.
*/ 2 -> legalIdentities[1]
private fun getAllNodeInfos(nodesDirs: List<Path>): List<NodeInfo> { else -> throw IllegalArgumentException("Not sure how to get the notary identity in this scenerio: $this")
val nodeInfoFiles = nodesDirs.map { dir ->
dir.list { it.filter { "nodeInfo-" in it.toString() }.findFirst().get() }
} }
return nodeInfoFiles.mapNotNull { processFile(it) }
} }
private fun processFile(file: Path): NodeInfo? { private fun processFile(file: Path): NodeInfo? {
@ -92,8 +88,6 @@ class TestNetworkParametersGenerator : NetworkParametersGenerator {
} }
} }
private fun NodeInfo.notaryIdentity() = if (legalIdentities.size == 2) legalIdentities[1] else legalIdentities[0]
// We need to to set serialization env, because generation of parameters is run from Cordform. // We need to to set serialization env, because generation of parameters is run from Cordform.
// KryoServerSerializationScheme is not accessible from nodeapi. // KryoServerSerializationScheme is not accessible from nodeapi.
private fun initialiseSerialization() { private fun initialiseSerialization() {
@ -103,14 +97,14 @@ class TestNetworkParametersGenerator : NetworkParametersGenerator {
registerScheme(KryoParametersSerializationScheme) registerScheme(KryoParametersSerializationScheme)
registerScheme(AMQPServerSerializationScheme()) registerScheme(AMQPServerSerializationScheme())
}, },
context)) context)
)
} }
private object KryoParametersSerializationScheme : AbstractKryoSerializationScheme() { private object KryoParametersSerializationScheme : AbstractKryoSerializationScheme() {
override fun canDeserializeVersion(byteSequence: ByteSequence, target: SerializationContext.UseCase): Boolean { override fun canDeserializeVersion(byteSequence: ByteSequence, target: SerializationContext.UseCase): Boolean {
return byteSequence == KryoHeaderV0_1 && target == SerializationContext.UseCase.P2P return byteSequence == KryoHeaderV0_1 && target == SerializationContext.UseCase.P2P
} }
override fun rpcClientKryoPool(context: SerializationContext) = throw UnsupportedOperationException() override fun rpcClientKryoPool(context: SerializationContext) = throw UnsupportedOperationException()
override fun rpcServerKryoPool(context: SerializationContext) = throw UnsupportedOperationException() override fun rpcServerKryoPool(context: SerializationContext) = throw UnsupportedOperationException()
} }