diff --git a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt index 4c2f0e4b04..ed60495ccd 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -152,7 +152,6 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, lateinit var keyManagement: KeyManagementService var inNodeNetworkMapService: NetworkMapService? = null var inNodeNotaryService: NotaryService? = null - var uniquenessProvider: UniquenessProvider? = null lateinit var identity: IdentityService lateinit var net: MessagingServiceInternal lateinit var netMapCache: NetworkMapCache @@ -200,38 +199,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, // Do all of this in a database transaction so anything that might need a connection has one. initialiseDatabasePersistence { - val storageServices = initialiseStorageService(configuration.baseDirectory) - storage = storageServices.first - checkpointStorage = storageServices.second - netMapCache = InMemoryNetworkMapCache() - net = makeMessagingService() - schemas = makeSchemaService() - vault = makeVaultService(configuration.dataSourceProperties) - - info = makeInfo() - identity = makeIdentityService() - // Place the long term identity key in the KMS. Eventually, this is likely going to be separated again because - // the KMS is meant for derived temporary keys used in transactions, and we're not supposed to sign things with - // the identity key. But the infrastructure to make that easy isn't here yet. - keyManagement = makeKeyManagementService() - flowLogicFactory = initialiseFlowLogicFactory() - scheduler = NodeSchedulerService(database, services, flowLogicFactory, unfinishedSchedules = busyNodeLatch) - - val tokenizableServices = mutableListOf(storage, net, vault, keyManagement, identity, platformClock, scheduler) - - customServices.clear() - customServices.addAll(buildPluginServices(tokenizableServices)) - - val uploaders: List = listOf(storageServices.first.attachments as NodeAttachmentService) + - customServices.filterIsInstance(AcceptsFileUpload::class.java) - (storage as StorageServiceImpl).initUploaders(uploaders) - - // TODO: uniquenessProvider creation should be inside makeNotaryService(), but notary service initialisation - // depends on smm, while smm depends on tokenizableServices, which uniquenessProvider is part of - advertisedServices.singleOrNull { it.type.isNotary() }?.let { - uniquenessProvider = makeUniquenessProvider(it.type) - tokenizableServices.add(uniquenessProvider!!) - } + val tokenizableServices = makeServices() smm = StateMachineManager(services, listOf(tokenizableServices), @@ -248,13 +216,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, } } - buildAdvertisedServices() - - // TODO: this model might change but for now it provides some de-coupling - // Add vault observers - CashBalanceAsMetricsObserver(services, database) - ScheduledActivityObserver(services) - HibernateObserver(services) + makeVaultObservers() checkpointStorage.forEach { isPreviousCheckpointsPresent = true @@ -273,6 +235,50 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, return this } + /** + * Builds node internal, advertised, and plugin services. + * Returns a list of tokenizable services to be added to the serialisation context. + */ + private fun makeServices(): MutableList { + val storageServices = initialiseStorageService(configuration.baseDirectory) + storage = storageServices.first + checkpointStorage = storageServices.second + netMapCache = InMemoryNetworkMapCache() + net = makeMessagingService() + schemas = makeSchemaService() + vault = makeVaultService(configuration.dataSourceProperties) + + info = makeInfo() + identity = makeIdentityService() + // Place the long term identity key in the KMS. Eventually, this is likely going to be separated again because + // the KMS is meant for derived temporary keys used in transactions, and we're not supposed to sign things with + // the identity key. But the infrastructure to make that easy isn't here yet. + keyManagement = makeKeyManagementService() + flowLogicFactory = initialiseFlowLogicFactory() + scheduler = NodeSchedulerService(database, services, flowLogicFactory, unfinishedSchedules = busyNodeLatch) + + val tokenizableServices = mutableListOf(storage, net, vault, keyManagement, identity, platformClock, scheduler) + makeAdvertisedServices(tokenizableServices) + + customServices.clear() + customServices.addAll(makePluginServices(tokenizableServices)) + + initUploaders(storageServices) + return tokenizableServices + } + + private fun initUploaders(storageServices: Pair) { + val uploaders: List = listOf(storageServices.first.attachments as NodeAttachmentService) + + customServices.filterIsInstance(AcceptsFileUpload::class.java) + (storage as StorageServiceImpl).initUploaders(uploaders) + } + + private fun makeVaultObservers() { + CashBalanceAsMetricsObserver(services, database) + ScheduledActivityObserver(services) + HibernateObserver(services) + } + private fun makeInfo(): NodeInfo { val advertisedServiceEntries = makeServiceEntries() val legalIdentity = obtainLegalIdentity() @@ -345,7 +351,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, return FlowLogicRefFactory(flowWhitelist) } - private fun buildPluginServices(tokenizableServices: MutableList): List { + private fun makePluginServices(tokenizableServices: MutableList): List { val pluginServices = pluginRegistries.flatMap { x -> x.servicePlugins } val serviceList = mutableListOf() for (serviceConstructor in pluginServices) { @@ -364,13 +370,13 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, return this } - private fun buildAdvertisedServices() { + private fun makeAdvertisedServices(tokenizableServices: MutableList) { val serviceTypes = info.advertisedServices.map { it.info.type } if (NetworkMapService.type in serviceTypes) makeNetworkMapService() val notaryServiceType = serviceTypes.singleOrNull { it.isNotary() } if (notaryServiceType != null) { - inNodeNotaryService = makeNotaryService(notaryServiceType) + inNodeNotaryService = makeNotaryService(notaryServiceType, tokenizableServices) } } @@ -426,13 +432,15 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, inNodeNetworkMapService = PersistentNetworkMapService(services) } - open protected fun makeNotaryService(type: ServiceType): NotaryService { + open protected fun makeNotaryService(type: ServiceType, tokenizableServices: MutableList): NotaryService { val timestampChecker = TimestampChecker(platformClock, 30.seconds) + val uniquenessProvider = makeUniquenessProvider(type) + tokenizableServices.add(uniquenessProvider) return when (type) { - SimpleNotaryService.type -> SimpleNotaryService(services, timestampChecker, uniquenessProvider!!) - ValidatingNotaryService.type -> ValidatingNotaryService(services, timestampChecker, uniquenessProvider!!) - RaftValidatingNotaryService.type -> RaftValidatingNotaryService(services, timestampChecker, uniquenessProvider!! as RaftUniquenessProvider) + SimpleNotaryService.type -> SimpleNotaryService(services, timestampChecker, uniquenessProvider) + ValidatingNotaryService.type -> ValidatingNotaryService(services, timestampChecker, uniquenessProvider) + RaftValidatingNotaryService.type -> RaftValidatingNotaryService(services, timestampChecker, uniquenessProvider as RaftUniquenessProvider) else -> { throw IllegalArgumentException("Notary type ${type.id} is not handled by makeNotaryService.") }