mirror of
https://github.com/corda/corda.git
synced 2025-06-18 23:28:21 +00:00
Raft notaries can share a single key pair for the service identity (i… (#2269)
* Raft notaries can share a single key pair for the service identity (in contrast to a shared composite public key, and individual signing key pairs). This allows adjusting the cluster size on the fly.
This commit is contained in:
@ -14,10 +14,12 @@ data class NotarySpec(
|
||||
)
|
||||
|
||||
@DoNotImplement
|
||||
sealed class ClusterSpec {
|
||||
abstract class ClusterSpec {
|
||||
abstract val clusterSize: Int
|
||||
|
||||
data class Raft(override val clusterSize: Int) : ClusterSpec() {
|
||||
data class Raft(
|
||||
override val clusterSize: Int
|
||||
) : ClusterSpec() {
|
||||
init {
|
||||
require(clusterSize > 0)
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ class DriverDSLImpl(
|
||||
if (cordform.notary == null) continue
|
||||
val name = CordaX500Name.parse(cordform.name)
|
||||
val notaryConfig = ConfigFactory.parseMap(cordform.notary).parseAs<NotaryConfig>()
|
||||
// We need to first group the nodes that form part of a cluser. We assume for simplicity that nodes of the
|
||||
// We need to first group the nodes that form part of a cluster. We assume for simplicity that nodes of the
|
||||
// same cluster type and validating flag are part of the same cluster.
|
||||
if (notaryConfig.raft != null) {
|
||||
val key = if (notaryConfig.validating) VALIDATING_RAFT else NON_VALIDATING_RAFT
|
||||
@ -282,10 +282,17 @@ class DriverDSLImpl(
|
||||
}
|
||||
|
||||
clusterNodes.asMap().forEach { type, nodeNames ->
|
||||
val identity = DevIdentityGenerator.generateDistributedNotaryIdentity(
|
||||
dirs = nodeNames.map { baseDirectory(it) },
|
||||
notaryName = type.clusterName
|
||||
)
|
||||
val identity = if (type == ClusterType.NON_VALIDATING_RAFT || type == ClusterType.VALIDATING_RAFT) {
|
||||
DevIdentityGenerator.generateDistributedNotarySingularIdentity(
|
||||
dirs = nodeNames.map { baseDirectory(it) },
|
||||
notaryName = type.clusterName
|
||||
)
|
||||
} else {
|
||||
DevIdentityGenerator.generateDistributedNotaryCompositeIdentity(
|
||||
dirs = nodeNames.map { baseDirectory(it) },
|
||||
notaryName = type.clusterName
|
||||
)
|
||||
}
|
||||
notaryInfos += NotaryInfo(identity, type.validating)
|
||||
}
|
||||
|
||||
@ -382,13 +389,30 @@ class DriverDSLImpl(
|
||||
private fun startNotaryIdentityGeneration(): CordaFuture<List<NotaryInfo>> {
|
||||
return executorService.fork {
|
||||
notarySpecs.map { spec ->
|
||||
val identity = if (spec.cluster == null) {
|
||||
DevIdentityGenerator.installKeyStoreWithNodeIdentity(baseDirectory(spec.name), spec.name)
|
||||
} else {
|
||||
DevIdentityGenerator.generateDistributedNotaryIdentity(
|
||||
dirs = generateNodeNames(spec).map { baseDirectory(it) },
|
||||
notaryName = spec.name
|
||||
)
|
||||
val identity = when (spec.cluster) {
|
||||
null -> {
|
||||
DevIdentityGenerator.installKeyStoreWithNodeIdentity(baseDirectory(spec.name), spec.name)
|
||||
}
|
||||
is ClusterSpec.Raft -> {
|
||||
DevIdentityGenerator.generateDistributedNotarySingularIdentity(
|
||||
dirs = generateNodeNames(spec).map { baseDirectory(it) },
|
||||
notaryName = spec.name
|
||||
)
|
||||
}
|
||||
is DummyClusterSpec -> {
|
||||
if (spec.cluster.compositeServiceIdentity) {
|
||||
DevIdentityGenerator.generateDistributedNotarySingularIdentity(
|
||||
dirs = generateNodeNames(spec).map { baseDirectory(it) },
|
||||
notaryName = spec.name
|
||||
)
|
||||
} else {
|
||||
DevIdentityGenerator.generateDistributedNotaryCompositeIdentity(
|
||||
dirs = generateNodeNames(spec).map { baseDirectory(it) },
|
||||
notaryName = spec.name
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> throw UnsupportedOperationException("Cluster spec ${spec.cluster} not supported by Driver")
|
||||
}
|
||||
NotaryInfo(identity, spec.validating)
|
||||
}
|
||||
@ -433,9 +457,12 @@ class DriverDSLImpl(
|
||||
|
||||
private fun startNotaries(localNetworkMap: LocalNetworkMap?): List<CordaFuture<List<NodeHandle>>> {
|
||||
return notarySpecs.map {
|
||||
when {
|
||||
it.cluster == null -> startSingleNotary(it, localNetworkMap)
|
||||
it.cluster is ClusterSpec.Raft -> startRaftNotaryCluster(it, localNetworkMap)
|
||||
when (it.cluster) {
|
||||
null -> startSingleNotary(it, localNetworkMap)
|
||||
is ClusterSpec.Raft,
|
||||
// DummyCluster is used for testing the notary communication path, and it does not matter
|
||||
// which underlying consensus algorithm is used, so we just stick to Raft
|
||||
is DummyClusterSpec -> startRaftNotaryCluster(it, localNetworkMap)
|
||||
else -> throw IllegalArgumentException("BFT-SMaRt not supported")
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package net.corda.testing.node.internal
|
||||
|
||||
import net.corda.testing.node.ClusterSpec
|
||||
|
||||
/**
|
||||
* Only used for testing the notary communication path. Can be configured to act as a Raft (singular identity),
|
||||
* or a BFT (composite key identity) notary service.
|
||||
*/
|
||||
data class DummyClusterSpec(
|
||||
override val clusterSize: Int,
|
||||
/**
|
||||
* If *true*, the cluster will use a shared composite public key for the service identity, with individual
|
||||
* private keys. If *false*, the same "singular" key pair will be shared by all replicas.
|
||||
*/
|
||||
val compositeServiceIdentity: Boolean = false
|
||||
) : ClusterSpec() {
|
||||
init {
|
||||
require(clusterSize > 0)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user