Add advertised services to NodeInfo

This commit is contained in:
Ross Nicoll 2016-04-07 17:13:56 +01:00
parent b35fd814d2
commit acee02f876
7 changed files with 46 additions and 10 deletions

View File

@ -90,6 +90,8 @@ abstract class AbstractNode(val dir: Path, val configuration: NodeConfiguration,
lateinit var api: APIServer lateinit var api: APIServer
open fun start(): AbstractNode { open fun start(): AbstractNode {
require(timestamperAddress == null || timestamperAddress.advertisedServices.contains(ServiceType.Timestamping),
{"Timestamper address must indicate a node that provides timestamping services"})
log.info("Node starting up ...") log.info("Node starting up ...")
storage = initialiseStorageService(dir) storage = initialiseStorageService(dir)
@ -117,7 +119,7 @@ abstract class AbstractNode(val dir: Path, val configuration: NodeConfiguration,
timestamperAddress timestamperAddress
} else { } else {
inNodeTimestampingService = NodeTimestamperService(net, storage.myLegalIdentity, storage.myLegalIdentityKey, platformClock) inNodeTimestampingService = NodeTimestamperService(net, storage.myLegalIdentity, storage.myLegalIdentityKey, platformClock)
NodeInfo(net.myAddress, storage.myLegalIdentity) NodeInfo(net.myAddress, storage.myLegalIdentity, advertisedServices = setOf(ServiceType.Timestamping))
} }
(services.networkMapCache as MockNetworkMapCache).timestampingNodes.add(tsid) (services.networkMapCache as MockNetworkMapCache).timestampingNodes.add(tsid)
} }

View File

@ -9,7 +9,8 @@ import java.util.*
* Info about a network node that acts on behalf of some sort of verified identity. * Info about a network node that acts on behalf of some sort of verified identity.
*/ */
data class NodeInfo(val address: SingleMessageRecipient, val identity: Party, data class NodeInfo(val address: SingleMessageRecipient, val identity: Party,
val physicalLocation: PhysicalLocation? = null) val physicalLocation: PhysicalLocation? = null,
var advertisedServices: Set<ServiceType> = emptySet())
/** /**
* A network map contains lists of nodes on the network along with information about their identity keys, services * A network map contains lists of nodes on the network along with information about their identity keys, services

View File

@ -0,0 +1,24 @@
/*
* Copyright 2016 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services
/**
* Enum for the possible services a node can expose
*/
enum class ServiceType {
Identity,
KeyManagement,
Messaging,
Monitoring,
NetworkMap,
RatesOracle,
Timestamping,
Storage,
Wallet
}

View File

@ -9,6 +9,7 @@ import core.messaging.*
import core.node.services.DummyTimestampingAuthority import core.node.services.DummyTimestampingAuthority
import core.node.services.NodeInfo import core.node.services.NodeInfo
import core.node.services.NodeTimestamperService import core.node.services.NodeTimestamperService
import core.node.services.ServiceType
import core.utilities.loggerFor import core.utilities.loggerFor
import rx.Observable import rx.Observable
import rx.subjects.PublishSubject import rx.subjects.PublishSubject
@ -150,7 +151,7 @@ class InMemoryMessagingNetwork {
val (handle, builder) = createNode(manuallyPumped) val (handle, builder) = createNode(manuallyPumped)
val node = builder.start().get() val node = builder.start().get()
NodeTimestamperService(node, DummyTimestampingAuthority.identity, DummyTimestampingAuthority.key) NodeTimestamperService(node, DummyTimestampingAuthority.identity, DummyTimestampingAuthority.key)
timestampingAdvert = NodeInfo(handle, DummyTimestampingAuthority.identity) timestampingAdvert = NodeInfo(handle, DummyTimestampingAuthority.identity, advertisedServices = setOf(ServiceType.Timestamping))
return Pair(timestampingAdvert!!, node) return Pair(timestampingAdvert!!, node)
} }

View File

@ -10,6 +10,7 @@ import core.node.NodeConfiguration
import core.node.services.FixedIdentityService import core.node.services.FixedIdentityService
import core.node.services.NodeInfo import core.node.services.NodeInfo
import core.node.services.PhysicalLocation import core.node.services.PhysicalLocation
import core.node.services.ServiceType
import core.utilities.loggerFor import core.utilities.loggerFor
import org.slf4j.Logger import org.slf4j.Logger
import java.nio.file.Files import java.nio.file.Files
@ -90,7 +91,8 @@ class MockNetwork(private val threadPerNode: Boolean = false,
} }
/** Returns a started node, optionally created by the passed factory method */ /** Returns a started node, optionally created by the passed factory method */
fun createNode(withTimestamper: NodeInfo?, forcedID: Int = -1, nodeFactory: Factory = defaultFactory): MockNode { fun createNode(withTimestamper: NodeInfo?, forcedID: Int = -1, nodeFactory: Factory = defaultFactory,
advertisedServices: Set<ServiceType> = emptySet()): MockNode {
val newNode = forcedID == -1 val newNode = forcedID == -1
val id = if (newNode) counter++ else forcedID val id = if (newNode) counter++ else forcedID
@ -103,6 +105,7 @@ class MockNetwork(private val threadPerNode: Boolean = false,
override val nearestCity: String = "Atlantis" override val nearestCity: String = "Atlantis"
} }
val node = nodeFactory.create(path, config, this, withTimestamper).start() val node = nodeFactory.create(path, config, this, withTimestamper).start()
node.info.advertisedServices = advertisedServices
_nodes.add(node) _nodes.add(node)
return node return node
} }
@ -127,7 +130,10 @@ class MockNetwork(private val threadPerNode: Boolean = false,
*/ */
fun createTwoNodes(nodeFactory: Factory = defaultFactory): Pair<MockNode, MockNode> { fun createTwoNodes(nodeFactory: Factory = defaultFactory): Pair<MockNode, MockNode> {
require(nodes.isEmpty()) require(nodes.isEmpty())
return Pair(createNode(null, -1, nodeFactory), createNode(nodes[0].info, -1, nodeFactory)) return Pair(
createNode(null, -1, nodeFactory, setOf(ServiceType.Timestamping)),
createNode(nodes[0].info, -1, nodeFactory)
)
} }
fun addressToNode(address: SingleMessageRecipient): MockNode = nodes.single { it.net.myAddress == address } fun addressToNode(address: SingleMessageRecipient): MockNode = nodes.single { it.net.myAddress == address }

View File

@ -10,6 +10,7 @@ import core.node.NodeConfigurationFromConfig
import core.node.services.ArtemisMessagingService import core.node.services.ArtemisMessagingService
import core.node.services.MockNetworkMapCache import core.node.services.MockNetworkMapCache
import core.node.services.NodeInfo import core.node.services.NodeInfo
import core.node.services.ServiceType
import core.serialization.deserialize import core.serialization.deserialize
import core.utilities.BriefLogFormatter import core.utilities.BriefLogFormatter
import demos.protocols.AutoOfferProtocol import demos.protocols.AutoOfferProtocol
@ -71,7 +72,7 @@ fun main(args: Array<String>) {
null null
} else { } else {
try { try {
nodeInfo(options.valueOf(timestamperNetAddr), options.valueOf(timestamperIdentityFile)) nodeInfo(options.valueOf(timestamperNetAddr), options.valueOf(timestamperIdentityFile), setOf(ServiceType.Timestamping))
} catch (e: Exception) { } catch (e: Exception) {
null null
} }
@ -82,7 +83,7 @@ fun main(args: Array<String>) {
null null
} else { } else {
try { try {
nodeInfo(options.valueOf(rateOracleNetAddr), options.valueOf(rateOracleIdentityFile)) nodeInfo(options.valueOf(rateOracleNetAddr), options.valueOf(rateOracleIdentityFile), setOf(ServiceType.RatesOracle))
} catch (e: Exception) { } catch (e: Exception) {
null null
} }
@ -122,12 +123,12 @@ fun main(args: Array<String>) {
exitProcess(0) exitProcess(0)
} }
fun nodeInfo(hostAndPortString: String, identityFile: String): NodeInfo { fun nodeInfo(hostAndPortString: String, identityFile: String, advertisedServices: Set<ServiceType> = emptySet()): NodeInfo {
try { try {
val addr = HostAndPort.fromString(hostAndPortString).withDefaultPort(Node.DEFAULT_PORT) val addr = HostAndPort.fromString(hostAndPortString).withDefaultPort(Node.DEFAULT_PORT)
val path = Paths.get(identityFile) val path = Paths.get(identityFile)
val party = Files.readAllBytes(path).deserialize<Party>(includeClassName = true) val party = Files.readAllBytes(path).deserialize<Party>(includeClassName = true)
return NodeInfo(ArtemisMessagingService.makeRecipient(addr), party) return NodeInfo(ArtemisMessagingService.makeRecipient(addr), party, advertisedServices = advertisedServices)
} catch (e: Exception) { } catch (e: Exception) {
println("Could not find identify file $identityFile. If the file has just been created as part of starting the demo, please restart this node") println("Could not find identify file $identityFile. If the file has just been created as part of starting the demo, please restart this node")
throw e throw e

View File

@ -6,6 +6,7 @@ import core.crypto.sha256
import core.node.NodeConfiguration import core.node.NodeConfiguration
import core.node.services.NodeAttachmentService import core.node.services.NodeAttachmentService
import core.node.services.NodeInfo import core.node.services.NodeInfo
import core.node.services.ServiceType
import core.serialization.OpaqueBytes import core.serialization.OpaqueBytes
import core.testing.MockNetwork import core.testing.MockNetwork
import core.testutils.rootCauseExceptions import core.testutils.rootCauseExceptions
@ -95,7 +96,7 @@ class AttachmentTests {
} }
} }
} }
}) }, advertisedServices = setOf(ServiceType.Timestamping))
val n1 = network.createNode(n0.info) val n1 = network.createNode(n0.info)
// Insert an attachment into node zero's store directly. // Insert an attachment into node zero's store directly.