mirror of
https://github.com/corda/corda.git
synced 2025-01-30 16:14:39 +00:00
Extended Driver api to allow custom config overrides. Added helper methods for creating a distributed notary cluster.
This commit is contained in:
parent
8119a343fe
commit
758ab6d359
@ -11,6 +11,7 @@ import net.corda.core.div
|
|||||||
import net.corda.core.future
|
import net.corda.core.future
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
|
import net.corda.core.node.services.ServiceType
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.node.services.User
|
import net.corda.node.services.User
|
||||||
import net.corda.node.services.config.ConfigHelper
|
import net.corda.node.services.config.ConfigHelper
|
||||||
@ -18,7 +19,9 @@ import net.corda.node.services.config.FullNodeConfiguration
|
|||||||
import net.corda.node.services.messaging.ArtemisMessagingServer
|
import net.corda.node.services.messaging.ArtemisMessagingServer
|
||||||
import net.corda.node.services.messaging.NodeMessagingClient
|
import net.corda.node.services.messaging.NodeMessagingClient
|
||||||
import net.corda.node.services.network.NetworkMapService
|
import net.corda.node.services.network.NetworkMapService
|
||||||
|
import net.corda.node.services.transactions.RaftValidatingNotaryService
|
||||||
import net.corda.node.utilities.JsonSupport
|
import net.corda.node.utilities.JsonSupport
|
||||||
|
import net.corda.node.utilities.ServiceIdentityGenerator
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.*
|
import java.net.*
|
||||||
@ -62,7 +65,17 @@ interface DriverDSLExposedInterface {
|
|||||||
*/
|
*/
|
||||||
fun startNode(providedName: String? = null,
|
fun startNode(providedName: String? = null,
|
||||||
advertisedServices: Set<ServiceInfo> = emptySet(),
|
advertisedServices: Set<ServiceInfo> = emptySet(),
|
||||||
rpcUsers: List<User> = emptyList()): Future<NodeInfoAndConfig>
|
rpcUsers: List<User> = emptyList(),
|
||||||
|
customOverrides: Map<String, Any?> = emptyMap()): Future<NodeInfoAndConfig>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a distributed notary cluster.
|
||||||
|
*
|
||||||
|
* @param notaryName The legal name of the advertised distributed notary service.
|
||||||
|
* @param clusterSize Number of nodes to create for the cluster.
|
||||||
|
* @param type The advertised notary service type. Currently the only supported type is [RaftValidatingNotaryService.type].
|
||||||
|
*/
|
||||||
|
fun startNotaryCluster(notaryName: String, clusterSize: Int = 3, type: ServiceType = RaftValidatingNotaryService.type)
|
||||||
|
|
||||||
fun waitForAllNodesToFinish()
|
fun waitForAllNodesToFinish()
|
||||||
}
|
}
|
||||||
@ -292,31 +305,35 @@ open class DriverDSL(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startNode(providedName: String?, advertisedServices: Set<ServiceInfo>, rpcUsers: List<User>): Future<NodeInfoAndConfig> {
|
override fun startNode(providedName: String?, advertisedServices: Set<ServiceInfo>,
|
||||||
|
rpcUsers: List<User>, customOverrides: Map<String, Any?>): Future<NodeInfoAndConfig> {
|
||||||
val messagingAddress = portAllocation.nextHostAndPort()
|
val messagingAddress = portAllocation.nextHostAndPort()
|
||||||
val apiAddress = portAllocation.nextHostAndPort()
|
val apiAddress = portAllocation.nextHostAndPort()
|
||||||
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
||||||
val name = providedName ?: "${pickA(name)}-${messagingAddress.port}"
|
val name = providedName ?: "${pickA(name)}-${messagingAddress.port}"
|
||||||
|
|
||||||
val baseDirectory = driverDirectory / name
|
val baseDirectory = driverDirectory / name
|
||||||
|
val configOverrides = mapOf(
|
||||||
|
"myLegalName" to name,
|
||||||
|
"basedir" to baseDirectory.normalize().toString(),
|
||||||
|
"artemisAddress" to messagingAddress.toString(),
|
||||||
|
"webAddress" to apiAddress.toString(),
|
||||||
|
"extraAdvertisedServiceIds" to advertisedServices.joinToString(","),
|
||||||
|
"networkMapAddress" to networkMapAddress.toString(),
|
||||||
|
"useTestClock" to useTestClock,
|
||||||
|
"rpcUsers" to rpcUsers.map {
|
||||||
|
mapOf(
|
||||||
|
"user" to it.username,
|
||||||
|
"password" to it.password,
|
||||||
|
"permissions" to it.permissions
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) + customOverrides
|
||||||
|
|
||||||
val config = ConfigHelper.loadConfig(
|
val config = ConfigHelper.loadConfig(
|
||||||
baseDirectoryPath = baseDirectory,
|
baseDirectoryPath = baseDirectory,
|
||||||
allowMissingConfig = true,
|
allowMissingConfig = true,
|
||||||
configOverrides = mapOf(
|
configOverrides = configOverrides
|
||||||
"myLegalName" to name,
|
|
||||||
"basedir" to baseDirectory.normalize().toString(),
|
|
||||||
"artemisAddress" to messagingAddress.toString(),
|
|
||||||
"webAddress" to apiAddress.toString(),
|
|
||||||
"extraAdvertisedServiceIds" to advertisedServices.joinToString(","),
|
|
||||||
"networkMapAddress" to networkMapAddress.toString(),
|
|
||||||
"useTestClock" to useTestClock,
|
|
||||||
"rpcUsers" to rpcUsers.map { mapOf(
|
|
||||||
"user" to it.username,
|
|
||||||
"password" to it.password,
|
|
||||||
"permissions" to it.permissions)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return future {
|
return future {
|
||||||
@ -325,6 +342,25 @@ open class DriverDSL(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun startNotaryCluster(notaryName: String, clusterSize: Int, type: ServiceType) {
|
||||||
|
val nodeNames = (1..clusterSize).map { "Notary Node $it" }
|
||||||
|
val paths = nodeNames.map { driverDirectory / it }
|
||||||
|
ServiceIdentityGenerator.generateToDisk(paths, type.id, notaryName)
|
||||||
|
|
||||||
|
val serviceInfo = ServiceInfo(type, notaryName)
|
||||||
|
val advertisedService = setOf(serviceInfo)
|
||||||
|
val notaryClusterAddress = portAllocation.nextHostAndPort()
|
||||||
|
|
||||||
|
// Start the first node that will bootstrap the cluster
|
||||||
|
startNode(nodeNames.first(), advertisedService, emptyList(), mapOf("notaryNodeAddress" to notaryClusterAddress.toString()))
|
||||||
|
// All other nodes will join the cluster
|
||||||
|
nodeNames.drop(1).forEach {
|
||||||
|
val nodeAddress = portAllocation.nextHostAndPort()
|
||||||
|
val configOverride = mapOf("notaryNodeAddress" to nodeAddress.toString(), "notaryClusterAddress" to notaryClusterAddress.toString())
|
||||||
|
startNode(it, advertisedService, emptyList(), configOverride)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun start() {
|
override fun start() {
|
||||||
startNetworkMapService()
|
startNetworkMapService()
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package net.corda.node.utilities
|
||||||
|
|
||||||
|
import net.corda.core.crypto.CompositeKey
|
||||||
|
import net.corda.core.crypto.Party
|
||||||
|
import net.corda.core.crypto.composite
|
||||||
|
import net.corda.core.crypto.generateKeyPair
|
||||||
|
import net.corda.core.serialization.serialize
|
||||||
|
import net.corda.core.utilities.loggerFor
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
object ServiceIdentityGenerator {
|
||||||
|
private val log = loggerFor<ServiceIdentityGenerator>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates signing key pairs and a common distributed service identity for a set of nodes.
|
||||||
|
* The key pairs and the group identity get serialized to disk in the corresponding node directories.
|
||||||
|
* This method should be called *before* any of the nodes are started.
|
||||||
|
*
|
||||||
|
* @param dirs List of node directories to place the generated identity and key pairs in.
|
||||||
|
* @param serviceId The service id of the distributed service.
|
||||||
|
* @param serviceName The legal name of the distributed service.
|
||||||
|
* @param threshold The threshold for the generated group [CompositeKey.Node].
|
||||||
|
*/
|
||||||
|
fun generateToDisk(dirs: List<Path>, serviceId: String, serviceName: String, threshold: Int = 1) {
|
||||||
|
log.trace("Generating a group identity \"serviceName\" for nodes: ${dirs.joinToString()}")
|
||||||
|
|
||||||
|
val keyPairs = (1..dirs.size).map { generateKeyPair() }
|
||||||
|
val notaryKey = CompositeKey.Builder().addKeys(keyPairs.map { it.public.composite }).build(threshold)
|
||||||
|
val notaryParty = Party(serviceName, notaryKey).serialize()
|
||||||
|
|
||||||
|
keyPairs.zip(dirs) { keyPair, dir ->
|
||||||
|
Files.createDirectories(dir)
|
||||||
|
val privateKeyFile = serviceId + "-private-key"
|
||||||
|
val publicKeyFile = serviceId + "-public"
|
||||||
|
notaryParty.writeToFile(dir.resolve(publicKeyFile))
|
||||||
|
keyPair.serialize().writeToFile(dir.resolve(privateKeyFile))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user