Advertised services now contain ServiceInfo which describes ServiceType and a service identifier. This will be used, e.g. for grouping distributed notary nodes into the same service cluster.

This commit is contained in:
Andrius Dagys
2016-10-03 10:44:33 +01:00
parent 4ed73dc9f2
commit 5efa0fd5b3
22 changed files with 110 additions and 84 deletions

View File

@ -2,6 +2,7 @@ package com.r3corda.node.driver
import com.r3corda.core.node.NodeInfo
import com.r3corda.core.node.services.NetworkMapCache
import com.r3corda.core.node.services.ServiceInfo
import com.r3corda.node.services.api.RegulatorService
import com.r3corda.node.services.messaging.ArtemisMessagingComponent
import com.r3corda.node.services.transactions.SimpleNotaryService
@ -32,8 +33,8 @@ class DriverTests {
@Test
fun simpleNodeStartupShutdownWorks() {
val (notary, regulator) = driver {
val notary = startNode("TestNotary", setOf(SimpleNotaryService.Type))
val regulator = startNode("Regulator", setOf(RegulatorService.Type))
val notary = startNode("TestNotary", setOf(ServiceInfo(SimpleNotaryService.Type)))
val regulator = startNode("Regulator", setOf(ServiceInfo(RegulatorService.Type)))
nodeMustBeUp(networkMapCache, notary.get(), "TestNotary")
nodeMustBeUp(networkMapCache, regulator.get(), "Regulator")

View File

@ -6,7 +6,7 @@ import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.generateKeyPair
import com.r3corda.core.node.NodeInfo
import com.r3corda.core.node.services.NetworkMapCache
import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.node.services.ServiceInfo
import com.r3corda.node.services.config.FullNodeConfiguration
import com.r3corda.node.services.config.NodeConfiguration
import com.r3corda.node.services.config.NodeConfigurationFromConfig
@ -56,7 +56,7 @@ interface DriverDSLExposedInterface {
* @param advertisedServices The set of services to be advertised by the node. Defaults to empty set.
* @return The [NodeInfo] of the started up node retrieved from the network map service.
*/
fun startNode(providedName: String? = null, advertisedServices: Set<ServiceType> = setOf()): Future<NodeInfo>
fun startNode(providedName: String? = null, advertisedServices: Set<ServiceInfo> = setOf()): Future<NodeInfo>
/**
* Starts an [NodeMessagingClient].
@ -286,14 +286,14 @@ class DriverDSL(
addressMustNotBeBound(networkMapAddress)
}
override fun startNode(providedName: String?, advertisedServices: Set<ServiceType>): Future<NodeInfo> {
override fun startNode(providedName: String?, advertisedServices: Set<ServiceInfo>): Future<NodeInfo> {
val messagingAddress = portAllocation.nextHostAndPort()
val apiAddress = portAllocation.nextHostAndPort()
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
val name = providedName ?: "${pickA(name)}-${messagingAddress.port}"
val nodeDirectory = "$baseDirectory/$name"
val useNotary = advertisedServices.any { it.isSubTypeOf(NotaryService.Type) }
val useNotary = advertisedServices.any { it.type.isSubTypeOf(NotaryService.Type) }
val config = NodeConfiguration.loadConfig(
baseDirectoryPath = Paths.get(nodeDirectory),
@ -304,7 +304,7 @@ class DriverDSL(
"artemisAddress" to messagingAddress.toString(),
"webAddress" to apiAddress.toString(),
"hostNotaryServiceLocally" to useNotary.toString(),
"extraAdvertisedServiceIds" to advertisedServices.map { x -> x.id }.joinToString(","),
"extraAdvertisedServiceIds" to advertisedServices.joinToString(","),
"networkMapAddress" to networkMapAddress.toString()
)
)
@ -446,7 +446,7 @@ class DriverDSL(
listOf("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$debugPort")
else
emptyList()
val javaArgs = listOf(path) +
listOf("-Dname=${nodeConf.myLegalName}", "-javaagent:$quasarJarPath") + debugPortArg +
listOf("-cp", classpath, className) +

View File

@ -71,7 +71,7 @@ import kotlin.reflect.KClass
// In theory the NodeInfo for the node should be passed in, instead, however currently this is constructed by the
// AbstractNode. It should be possible to generate the NodeInfo outside of AbstractNode, so it can be passed in.
abstract class AbstractNode(val configuration: NodeConfiguration, val networkMapService: SingleMessageRecipient?,
val advertisedServices: Set<ServiceType>, val platformClock: Clock) : SingletonSerializeAsToken() {
val advertisedServices: Set<ServiceInfo>, val platformClock: Clock) : SingletonSerializeAsToken() {
companion object {
val PRIVATE_KEY_FILE_NAME = "identity-private-key"
val PUBLIC_IDENTITY_FILE_NAME = "identity-public"
@ -211,7 +211,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, val networkMap
// 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.isSubTypeOf(NotaryService.Type) }?.let {
advertisedServices.singleOrNull { it.type.isSubTypeOf(NotaryService.Type) }?.let {
uniquenessProvider = makeUniquenessProvider()
tokenizableServices.add(uniquenessProvider!!)
}
@ -318,7 +318,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, val networkMap
}
private fun buildAdvertisedServices() {
val serviceTypes = info.advertisedServices
val serviceTypes = info.advertisedServices.map { it.type }
if (NetworkMapService.Type in serviceTypes) makeNetworkMapService()
val notaryServiceType = serviceTypes.singleOrNull { it.isSubTypeOf(NotaryService.Type) }
@ -332,7 +332,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, val networkMap
* updates) if one has been supplied.
*/
private fun registerWithNetworkMap(): ListenableFuture<Unit> {
require(networkMapService != null || NetworkMapService.Type in advertisedServices) {
require(networkMapService != null || NetworkMapService.Type in advertisedServices.map { it.type }) {
"Initial network map address must indicate a node that provides a network map service"
}
services.networkMapCache.addNode(info)

View File

@ -4,7 +4,7 @@ import com.codahale.metrics.JmxReporter
import com.google.common.net.HostAndPort
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.ServiceHub
import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.node.services.ServiceInfo
import com.r3corda.core.utilities.loggerFor
import com.r3corda.node.serialization.NodeClock
import com.r3corda.node.services.api.MessagingServiceInternal
@ -61,7 +61,7 @@ class ConfigurationException(message: String) : Exception(message)
*/
class Node(val p2pAddr: HostAndPort, val webServerAddr: HostAndPort,
configuration: NodeConfiguration, networkMapAddress: SingleMessageRecipient?,
advertisedServices: Set<ServiceType>, clock: Clock = NodeClock(),
advertisedServices: Set<ServiceInfo>, clock: Clock = NodeClock(),
val messagingServerAddr: HostAndPort? = null) : AbstractNode(configuration, networkMapAddress, advertisedServices, clock) {
companion object {
/** The port that is used by default if none is specified. As you know, 31337 is the most elite number. */

View File

@ -4,7 +4,7 @@ import com.google.common.net.HostAndPort
import com.r3corda.core.crypto.X509Utilities
import com.r3corda.core.div
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.node.services.ServiceInfo
import com.r3corda.node.internal.Node
import com.r3corda.node.serialization.NodeClock
import com.r3corda.node.services.messaging.NodeMessagingClient
@ -157,14 +157,14 @@ class FullNodeConfiguration(conf: Config) : NodeConfiguration {
val clock: Clock = NodeClock()
fun createNode(): Node {
val advertisedServices = mutableSetOf<ServiceType>()
if (hostNotaryServiceLocally) advertisedServices.add(SimpleNotaryService.Type)
val advertisedServices = mutableSetOf<ServiceInfo>()
if (hostNotaryServiceLocally) advertisedServices.add(ServiceInfo(SimpleNotaryService.Type))
if (!extraAdvertisedServiceIds.isNullOrEmpty()) {
for (serviceId in extraAdvertisedServiceIds.split(",")) {
advertisedServices.add(object : ServiceType(serviceId) {})
advertisedServices.add(ServiceInfo.parse(serviceId))
}
}
if (networkMapAddress == null) advertisedServices.add(NetworkMapService.Type)
if (networkMapAddress == null) advertisedServices.add(ServiceInfo(NetworkMapService.Type))
val networkMapMessageAddress: SingleMessageRecipient? = if (networkMapAddress == null) null else NodeMessagingClient.makeNetworkMapAddress(networkMapAddress)
return Node(artemisAddress,
webAddress,

View File

@ -51,7 +51,7 @@ open class InMemoryNetworkMapCache : SingletonSerializeAsToken(), NetworkMapCach
protected var registeredNodes = Collections.synchronizedMap(HashMap<Party, NodeInfo>())
override fun get() = registeredNodes.map { it.value }
override fun get(serviceType: ServiceType) = registeredNodes.filterValues { it.advertisedServices.any { it.isSubTypeOf(serviceType) } }.map { it.value }
override fun get(serviceType: ServiceType) = registeredNodes.filterValues { it.advertisedServices.any { it.type.isSubTypeOf(serviceType) } }.map { it.value }
override fun getRecommended(type: ServiceType, contract: Contract, vararg party: Party): NodeInfo? = get(type).firstOrNull()
override fun getNodeByLegalName(name: String) = get().singleOrNull { it.identity.name == name }
override fun getNodeByPublicKey(publicKey: PublicKey) = get().singleOrNull { it.identity.owningKey == publicKey }

View File

@ -4,16 +4,15 @@ import com.r3corda.core.contracts.Attachment
import com.r3corda.core.crypto.SecureHash
import com.r3corda.core.crypto.sha256
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.NodeInfo
import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.node.services.ServiceInfo
import com.r3corda.core.serialization.OpaqueBytes
import com.r3corda.testing.node.MockNetwork
import com.r3corda.node.services.config.NodeConfiguration
import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.persistence.NodeAttachmentService
import com.r3corda.node.services.transactions.SimpleNotaryService
import com.r3corda.protocols.FetchAttachmentsProtocol
import com.r3corda.protocols.FetchDataProtocol
import com.r3corda.testing.node.MockNetwork
import com.r3corda.testing.rootCauseExceptions
import org.junit.Before
import org.junit.Test
@ -21,7 +20,6 @@ import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.nio.ByteBuffer
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.StandardOpenOption
import java.security.KeyPair
import java.util.jar.JarOutputStream
@ -89,7 +87,7 @@ class AttachmentTests {
// Make a node that doesn't do sanity checking at load time.
val n0 = network.createNode(null, -1, object : MockNetwork.Factory {
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
advertisedServices: Set<ServiceInfo>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
return object : MockNetwork.MockNode(config, network, networkMapAddr, advertisedServices, id, keyPair) {
override fun start(): MockNetwork.MockNode {
super.start()
@ -98,7 +96,7 @@ class AttachmentTests {
}
}
}
}, true, null, null, NetworkMapService.Type, SimpleNotaryService.Type)
}, true, null, null, ServiceInfo(NetworkMapService.Type), ServiceInfo(SimpleNotaryService.Type))
val n1 = network.createNode(n0.info.address)
// Insert an attachment into node zero's store directly.

View File

@ -6,6 +6,7 @@ import com.r3corda.core.messaging.Message
import com.r3corda.core.messaging.TopicStringValidator
import com.r3corda.core.messaging.createMessage
import com.r3corda.core.node.services.DEFAULT_SESSION_ID
import com.r3corda.core.node.services.ServiceInfo
import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.testing.node.MockNetwork
import org.junit.Before
@ -40,7 +41,7 @@ class InMemoryMessagingTests {
@Test
fun basics() {
val node1 = network.createNode(advertisedServices = NetworkMapService.Type)
val node1 = network.createNode(advertisedServices = ServiceInfo(NetworkMapService.Type))
val node2 = network.createNode(networkMapAddress = node1.info.address)
val node3 = network.createNode(networkMapAddress = node1.info.address)
@ -69,7 +70,7 @@ class InMemoryMessagingTests {
@Test
fun broadcast() {
val node1 = network.createNode(advertisedServices = NetworkMapService.Type)
val node1 = network.createNode(advertisedServices = ServiceInfo(NetworkMapService.Type))
val node2 = network.createNode(networkMapAddress = node1.info.address)
val node3 = network.createNode(networkMapAddress = node1.info.address)
@ -88,7 +89,7 @@ class InMemoryMessagingTests {
*/
@Test
fun `skip unhandled messages`() {
val node1 = network.createNode(advertisedServices = NetworkMapService.Type)
val node1 = network.createNode(advertisedServices = ServiceInfo(NetworkMapService.Type))
val node2 = network.createNode(networkMapAddress = node1.info.address)
var received: Int = 0

View File

@ -162,7 +162,7 @@ class TwoPartyTradeProtocolTests {
// that Bob was waiting on before the reboot occurred.
bobNode = net.createNode(networkMapAddr, bobAddr.id, object : MockNetwork.Factory {
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
advertisedServices: Set<ServiceInfo>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
return MockNetwork.MockNode(config, network, networkMapAddr, advertisedServices, bobAddr.id, BOB_KEY)
}
}, true, BOB.name, BOB_KEY)
@ -192,7 +192,7 @@ class TwoPartyTradeProtocolTests {
// Create a node in the mock network ...
return net.createNode(networkMapAddr, -1, object : MockNetwork.Factory {
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
advertisedServices: Set<ServiceInfo>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
return object : MockNetwork.MockNode(config, network, networkMapAddr, advertisedServices, id, keyPair) {
// That constructs the storage service object in a customised way ...
override fun constructStorageService(

View File

@ -3,6 +3,7 @@ package com.r3corda.node.services
import com.r3corda.core.contracts.*
import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.generateKeyPair
import com.r3corda.core.node.services.ServiceInfo
import com.r3corda.core.seconds
import com.r3corda.core.utilities.DUMMY_NOTARY
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
@ -35,10 +36,10 @@ class NotaryChangeTests {
oldNotaryNode = net.createNode(
legalName = DUMMY_NOTARY.name,
keyPair = DUMMY_NOTARY_KEY,
advertisedServices = *arrayOf(NetworkMapService.Type, SimpleNotaryService.Type))
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.Type), ServiceInfo(SimpleNotaryService.Type)))
clientNodeA = net.createNode(networkMapAddress = oldNotaryNode.info.address)
clientNodeB = net.createNode(networkMapAddress = oldNotaryNode.info.address)
newNotaryNode = net.createNode(networkMapAddress = oldNotaryNode.info.address, advertisedServices = SimpleNotaryService.Type)
newNotaryNode = net.createNode(networkMapAddress = oldNotaryNode.info.address, advertisedServices = ServiceInfo(SimpleNotaryService.Type))
net.runNetwork() // Clear network map registration messages
}

View File

@ -2,6 +2,7 @@ package com.r3corda.node.services
import com.google.common.util.concurrent.ListenableFuture
import com.r3corda.core.contracts.TransactionType
import com.r3corda.core.node.services.ServiceInfo
import com.r3corda.core.crypto.DigitalSignature
import com.r3corda.core.seconds
import com.r3corda.core.transactions.SignedTransaction
@ -32,8 +33,7 @@ class NotaryServiceTests {
notaryNode = net.createNode(
legalName = DUMMY_NOTARY.name,
keyPair = DUMMY_NOTARY_KEY,
advertisedServices = *arrayOf(NetworkMapService.Type, SimpleNotaryService.Type)
)
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.Type), ServiceInfo(SimpleNotaryService.Type)))
clientNode = net.createNode(networkMapAddress = notaryNode.info.address, keyPair = MINI_CORP_KEY)
net.runNetwork() // Clear network map registration messages
}

View File

@ -2,22 +2,18 @@ package com.r3corda.node.services
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.NodeInfo
import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.node.services.ServiceInfo
import com.r3corda.node.services.api.ServiceHubInternal
import com.r3corda.node.services.config.NodeConfiguration
import com.r3corda.node.services.network.AbstractNetworkMapService
import com.r3corda.node.services.network.InMemoryNetworkMapService
import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.network.PersistentNetworkMapService
import com.r3corda.node.utilities.configureDatabase
import com.r3corda.node.utilities.databaseTransaction
import com.r3corda.testing.node.MockNetwork
import com.r3corda.testing.node.makeTestDataSourceProperties
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.io.Closeable
import java.nio.file.Path
import java.security.KeyPair
/**
@ -59,7 +55,7 @@ class PersistentNetworkMapServiceTest : AbstractNetworkMapServiceTest() {
private object NodeFactory : MockNetwork.Factory {
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
advertisedServices: Set<ServiceInfo>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
return object : MockNetwork.MockNode(config, network, networkMapAddr, advertisedServices, id, keyPair) {
override fun makeNetworkMapService() {

View File

@ -6,6 +6,7 @@ import com.r3corda.core.contracts.DummyContract
import com.r3corda.core.contracts.TransactionType
import com.r3corda.core.crypto.DigitalSignature
import com.r3corda.core.transactions.SignedTransaction
import com.r3corda.core.node.services.ServiceInfo
import com.r3corda.core.utilities.DUMMY_NOTARY
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
import com.r3corda.node.services.network.NetworkMapService
@ -33,7 +34,7 @@ class ValidatingNotaryServiceTests {
notaryNode = net.createNode(
legalName = DUMMY_NOTARY.name,
keyPair = DUMMY_NOTARY_KEY,
advertisedServices = *arrayOf(NetworkMapService.Type, ValidatingNotaryService.Type)
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.Type), ServiceInfo(ValidatingNotaryService.Type))
)
clientNode = net.createNode(networkMapAddress = notaryNode.info.address, keyPair = MINI_CORP_KEY)
net.runNetwork() // Clear network map registration messages