mirror of
https://github.com/corda/corda.git
synced 2025-06-16 22:28:15 +00:00
Fixed AbstractNode to load custom notary services properly (#1720)
* Fixed AbstractNode to load custom notary services properly. Added a custom notary sample. * Prevent multiple custom notaries from being loaded * Throw if more than once custom notary service is loaded
This commit is contained in:
@ -19,14 +19,11 @@ import net.corda.core.internal.concurrent.flatMap
|
||||
import net.corda.core.internal.concurrent.openFuture
|
||||
import net.corda.core.internal.toX509CertHolder
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.messaging.RPCOps
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.node.*
|
||||
import net.corda.core.messaging.*
|
||||
import net.corda.core.node.AppServiceHub
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.node.StateLoader
|
||||
import net.corda.core.node.services.*
|
||||
import net.corda.core.node.services.NetworkMapCache.MapChange
|
||||
import net.corda.core.schemas.MappedSchema
|
||||
@ -257,7 +254,8 @@ abstract class AbstractNode(config: NodeConfiguration,
|
||||
private class ServiceInstantiationException(cause: Throwable?) : CordaException("Service Instantiation Error", cause)
|
||||
|
||||
private fun installCordaServices() {
|
||||
cordappProvider.cordapps.flatMap { it.services }.forEach {
|
||||
val loadedServices = cordappProvider.cordapps.flatMap { it.services }
|
||||
filterServicesToInstall(loadedServices).forEach {
|
||||
try {
|
||||
installCordaService(it)
|
||||
} catch (e: NoSuchMethodException) {
|
||||
@ -271,6 +269,25 @@ abstract class AbstractNode(config: NodeConfiguration,
|
||||
}
|
||||
}
|
||||
|
||||
private fun filterServicesToInstall(loadedServices: List<Class<out SerializeAsToken>>): List<Class<out SerializeAsToken>> {
|
||||
val customNotaryServiceList = loadedServices.filter { isNotaryService(it) }
|
||||
if (customNotaryServiceList.isNotEmpty()) {
|
||||
if (configuration.notary?.custom == true) {
|
||||
require(customNotaryServiceList.size == 1) {
|
||||
"Attempting to install more than one notary service: ${customNotaryServiceList.joinToString()}"
|
||||
}
|
||||
}
|
||||
else return loadedServices - customNotaryServiceList
|
||||
}
|
||||
return loadedServices
|
||||
}
|
||||
|
||||
/**
|
||||
* If the [serviceClass] is a notary service, it will only be enable if the "custom" flag is set in
|
||||
* the notary configuration.
|
||||
*/
|
||||
private fun isNotaryService(serviceClass: Class<*>) = NotaryService::class.java.isAssignableFrom(serviceClass)
|
||||
|
||||
/**
|
||||
* This customizes the ServiceHub for each CordaService that is initiating flows
|
||||
*/
|
||||
@ -321,14 +338,15 @@ abstract class AbstractNode(config: NodeConfiguration,
|
||||
fun <T : SerializeAsToken> installCordaService(serviceClass: Class<T>): T {
|
||||
serviceClass.requireAnnotation<CordaService>()
|
||||
val service = try {
|
||||
if (NotaryService::class.java.isAssignableFrom(serviceClass)) {
|
||||
val serviceContext = AppServiceHubImpl<T>(services)
|
||||
if (isNotaryService(serviceClass)) {
|
||||
check(myNotaryIdentity != null) { "Trying to install a notary service but no notary identity specified" }
|
||||
val constructor = serviceClass.getDeclaredConstructor(ServiceHub::class.java, PublicKey::class.java).apply { isAccessible = true }
|
||||
constructor.newInstance(services, myNotaryIdentity!!.owningKey)
|
||||
val constructor = serviceClass.getDeclaredConstructor(AppServiceHub::class.java, PublicKey::class.java).apply { isAccessible = true }
|
||||
serviceContext.serviceInstance = constructor.newInstance(serviceContext, myNotaryIdentity!!.owningKey)
|
||||
serviceContext.serviceInstance
|
||||
} else {
|
||||
try {
|
||||
val extendedServiceConstructor = serviceClass.getDeclaredConstructor(AppServiceHub::class.java).apply { isAccessible = true }
|
||||
val serviceContext = AppServiceHubImpl<T>(services)
|
||||
serviceContext.serviceInstance = extendedServiceConstructor.newInstance(serviceContext)
|
||||
serviceContext.serviceInstance
|
||||
} catch (ex: NoSuchMethodException) {
|
||||
@ -688,7 +706,9 @@ abstract class AbstractNode(config: NodeConfiguration,
|
||||
// Node's main identity
|
||||
Pair("identity", myLegalName)
|
||||
} else {
|
||||
val notaryId = notaryConfig.run { NotaryService.constructId(validating, raft != null, bftSMaRt != null) }
|
||||
val notaryId = notaryConfig.run {
|
||||
NotaryService.constructId(validating, raft != null, bftSMaRt != null, custom)
|
||||
}
|
||||
if (notaryConfig.bftSMaRt == null && notaryConfig.raft == null) {
|
||||
// Node's notary identity
|
||||
Pair(notaryId, myLegalName.copy(commonName = notaryId))
|
||||
|
@ -36,9 +36,15 @@ interface NodeConfiguration : NodeSSLConfiguration {
|
||||
val additionalNodeInfoPollingFrequencyMsec: Long
|
||||
}
|
||||
|
||||
data class NotaryConfig(val validating: Boolean, val raft: RaftConfig? = null, val bftSMaRt: BFTSMaRtConfiguration? = null) {
|
||||
data class NotaryConfig(val validating: Boolean,
|
||||
val raft: RaftConfig? = null,
|
||||
val bftSMaRt: BFTSMaRtConfiguration? = null,
|
||||
val custom: Boolean = false
|
||||
) {
|
||||
init {
|
||||
require(raft == null || bftSMaRt == null) { "raft and bftSMaRt configs cannot be specified together" }
|
||||
require(raft == null || bftSMaRt == null || !custom) {
|
||||
"raft, bftSMaRt, and custom configs cannot be specified together"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,9 +52,10 @@ data class RaftConfig(val nodeAddress: NetworkHostAndPort, val clusterAddresses:
|
||||
|
||||
/** @param exposeRaces for testing only, so its default is not in reference.conf but here. */
|
||||
data class BFTSMaRtConfiguration constructor(val replicaId: Int,
|
||||
val clusterAddresses: List<NetworkHostAndPort>,
|
||||
val debug: Boolean = false,
|
||||
val exposeRaces: Boolean = false) {
|
||||
val clusterAddresses: List<NetworkHostAndPort>,
|
||||
val debug: Boolean = false,
|
||||
val exposeRaces: Boolean = false
|
||||
) {
|
||||
init {
|
||||
require(replicaId >= 0) { "replicaId cannot be negative" }
|
||||
}
|
||||
|
Reference in New Issue
Block a user