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:
Andrius Dagys
2018-01-09 08:17:59 +00:00
committed by GitHub
parent 4a995870c8
commit 3e00676851
10 changed files with 184 additions and 93 deletions

View File

@ -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)
}

View File

@ -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")
}
}

View File

@ -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)
}
}