From 265948dceeaec1bc67f52dc679d560146a8c67b1 Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Mon, 11 Apr 2016 10:01:39 +0100 Subject: [PATCH] Clean up code based on feedback from Mike * Move advertisedServices parameter in NodeInfo up one in the parameter order * Change ServiceType away from being an enum * Tweaked wording around what a NodeInfo is * Renamed LocationStructures to PhysicalLocationStructures * Move generator outside of function parameters --- .../core/node/services/IdentityService.kt | 1 + .../kotlin/core/node/services/ServiceType.kt | 33 +++++++++++++++++++ .../core/node/services/TimestamperService.kt | 1 + src/main/kotlin/core/node/AbstractNode.kt | 8 ++--- src/main/kotlin/core/node/NodeInfo.kt | 6 ++-- ...tures.kt => PhysicalLocationStructures.kt} | 0 .../core/node/services/NetworkMapCache.kt | 1 + .../core/node/services/NodeInterestRates.kt | 1 + .../kotlin/core/node/services/ServiceType.kt | 24 -------------- .../kotlin/core/node/services/Services.kt | 7 +++- .../core/testing/InMemoryMessagingNetwork.kt | 3 +- src/main/kotlin/core/testing/MockNode.kt | 3 +- src/main/kotlin/demos/IRSDemo.kt | 8 +++-- .../kotlin/core/messaging/AttachmentTests.kt | 4 +-- 14 files changed, 61 insertions(+), 39 deletions(-) create mode 100644 core/src/main/kotlin/core/node/services/ServiceType.kt rename src/main/kotlin/core/node/{LocationStructures.kt => PhysicalLocationStructures.kt} (100%) delete mode 100644 src/main/kotlin/core/node/services/ServiceType.kt diff --git a/core/src/main/kotlin/core/node/services/IdentityService.kt b/core/src/main/kotlin/core/node/services/IdentityService.kt index e89f3ca80b..506f3e7e6b 100644 --- a/core/src/main/kotlin/core/node/services/IdentityService.kt +++ b/core/src/main/kotlin/core/node/services/IdentityService.kt @@ -9,6 +9,7 @@ import java.security.PublicKey * service would provide. */ interface IdentityService { + object Type : ServiceType("corda.identity") fun partyFromKey(key: PublicKey): Party? fun partyFromName(name: String): Party? } diff --git a/core/src/main/kotlin/core/node/services/ServiceType.kt b/core/src/main/kotlin/core/node/services/ServiceType.kt new file mode 100644 index 0000000000..e8635002e5 --- /dev/null +++ b/core/src/main/kotlin/core/node/services/ServiceType.kt @@ -0,0 +1,33 @@ +/* + * 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 + +/** + * Identifier for service types a node can expose. + */ +abstract class ServiceType(val id: String) { + init { + // Enforce: + // + // * IDs must start with a lower case letter + // * IDs can only contain alphanumeric, full stop and underscore ASCII characters + require(id.matches(Regex("[a-z][a-zA-Z0-9._]+"))) + } + + override operator fun equals(other: Any?): Boolean = + if (other is ServiceType) { + id == other.id + } else { + false + } + + override fun hashCode(): Int = id.hashCode() + + override fun toString(): String = id.toString() +} \ No newline at end of file diff --git a/core/src/main/kotlin/core/node/services/TimestamperService.kt b/core/src/main/kotlin/core/node/services/TimestamperService.kt index 72d374f62f..544bf88ce0 100644 --- a/core/src/main/kotlin/core/node/services/TimestamperService.kt +++ b/core/src/main/kotlin/core/node/services/TimestamperService.kt @@ -15,6 +15,7 @@ import core.serialization.SerializedBytes * themselves. */ interface TimestamperService { + object Type : ServiceType("corda.timestamper") @Suspendable fun timestamp(wtxBytes: SerializedBytes): DigitalSignature.LegallyIdentifiable diff --git a/src/main/kotlin/core/node/AbstractNode.kt b/src/main/kotlin/core/node/AbstractNode.kt index d9c15c11a7..816ae493b5 100644 --- a/src/main/kotlin/core/node/AbstractNode.kt +++ b/src/main/kotlin/core/node/AbstractNode.kt @@ -59,7 +59,7 @@ abstract class AbstractNode(val dir: Path, val configuration: NodeConfiguration, } val info: NodeInfo by lazy { - NodeInfo(net.myAddress, storage.myLegalIdentity, findMyLocation()) + NodeInfo(net.myAddress, storage.myLegalIdentity, emptySet(), findMyLocation()) } protected open fun findMyLocation(): PhysicalLocation? = CityDatabase[configuration.nearestCity] @@ -91,8 +91,8 @@ abstract class AbstractNode(val dir: Path, val configuration: NodeConfiguration, lateinit var api: APIServer open fun start(): AbstractNode { - require(timestamperAddress == null || timestamperAddress.advertisedServices.contains(ServiceType.Timestamping), - {"Timestamper address must indicate a node that provides timestamping services"}) + require(timestamperAddress == null || timestamperAddress.advertisedServices.contains(TimestamperService.Type)) + {"Timestamper address must indicate a node that provides timestamping services"} log.info("Node starting up ...") storage = initialiseStorageService(dir) @@ -120,7 +120,7 @@ abstract class AbstractNode(val dir: Path, val configuration: NodeConfiguration, timestamperAddress } else { inNodeTimestampingService = NodeTimestamperService(net, storage.myLegalIdentity, storage.myLegalIdentityKey, platformClock) - NodeInfo(net.myAddress, storage.myLegalIdentity, advertisedServices = setOf(ServiceType.Timestamping)) + NodeInfo(net.myAddress, storage.myLegalIdentity, setOf(TimestamperService.Type)) } (services.networkMapCache as MockNetworkMapCache).timestampingNodes.add(tsid) } diff --git a/src/main/kotlin/core/node/NodeInfo.kt b/src/main/kotlin/core/node/NodeInfo.kt index d797a54e95..1e57e10640 100644 --- a/src/main/kotlin/core/node/NodeInfo.kt +++ b/src/main/kotlin/core/node/NodeInfo.kt @@ -12,8 +12,8 @@ import core.messaging.SingleMessageRecipient import core.node.services.ServiceType /** - * 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 form of contract party. */ data class NodeInfo(val address: SingleMessageRecipient, val identity: Party, - val physicalLocation: PhysicalLocation? = null, - var advertisedServices: Set = emptySet()) + var advertisedServices: Set = emptySet(), + val physicalLocation: PhysicalLocation? = null) diff --git a/src/main/kotlin/core/node/LocationStructures.kt b/src/main/kotlin/core/node/PhysicalLocationStructures.kt similarity index 100% rename from src/main/kotlin/core/node/LocationStructures.kt rename to src/main/kotlin/core/node/PhysicalLocationStructures.kt diff --git a/src/main/kotlin/core/node/services/NetworkMapCache.kt b/src/main/kotlin/core/node/services/NetworkMapCache.kt index 3742f84702..aa10ce4e67 100644 --- a/src/main/kotlin/core/node/services/NetworkMapCache.kt +++ b/src/main/kotlin/core/node/services/NetworkMapCache.kt @@ -17,6 +17,7 @@ import java.util.* * This interface assumes fast, synchronous access to an in-memory map. */ interface NetworkMapCache { + object Type : ServiceType("corda.network_map") val timestampingNodes: List val ratesOracleNodes: List val partyNodes: List diff --git a/src/main/kotlin/core/node/services/NodeInterestRates.kt b/src/main/kotlin/core/node/services/NodeInterestRates.kt index a1d292190e..cf583d4f0d 100644 --- a/src/main/kotlin/core/node/services/NodeInterestRates.kt +++ b/src/main/kotlin/core/node/services/NodeInterestRates.kt @@ -25,6 +25,7 @@ import javax.annotation.concurrent.ThreadSafe * for signing. */ object NodeInterestRates { + object Type : ServiceType("corda.interest_rates") /** Parses a string of the form "LIBOR 16-March-2016 1M = 0.678" into a [FixOf] and [Fix] */ fun parseOneRate(s: String): Pair { val (key, value) = s.split('=').map { it.trim() } diff --git a/src/main/kotlin/core/node/services/ServiceType.kt b/src/main/kotlin/core/node/services/ServiceType.kt deleted file mode 100644 index e516125235..0000000000 --- a/src/main/kotlin/core/node/services/ServiceType.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 -} \ No newline at end of file diff --git a/src/main/kotlin/core/node/services/Services.kt b/src/main/kotlin/core/node/services/Services.kt index 7438236dc7..f1ae4ff3d3 100644 --- a/src/main/kotlin/core/node/services/Services.kt +++ b/src/main/kotlin/core/node/services/Services.kt @@ -47,6 +47,7 @@ data class Wallet(val states: List>) { * consumed by someone else first! */ interface WalletService { + object Type : ServiceType("corda.wallet") /** * Returns a read-only snapshot of the wallet at the time the call is made. Note that if you consume states or * keys in this wallet, you must inform the wallet service so it can update its internal state. @@ -101,6 +102,7 @@ inline fun WalletService.linearHeadsOfType() = linearH * interface if/when one is developed. */ interface KeyManagementService { + object Type : ServiceType("corda.key_management") /** Returns a snapshot of the current pubkey->privkey mapping. */ val keys: Map @@ -116,6 +118,7 @@ interface KeyManagementService { * anything like that, this interface is only big enough to support the prototyping work. */ interface StorageService { + object Type : ServiceType("corda.storage") /** * A map of hash->tx where tx has been signature/contract validated and the states are known to be correct. * The signatures aren't technically needed after that point, but we keep them around so that we can relay @@ -172,7 +175,9 @@ interface AttachmentStorage { * Provides access to various metrics and ways to notify monitoring services of things, for sysadmin purposes. * This is not an interface because it is too lightweight to bother mocking out. */ -class MonitoringService(val metrics: MetricRegistry) +class MonitoringService(val metrics: MetricRegistry) { + object Type : ServiceType("corda.monitoring") +} /** * A service hub simply vends references to the other services a node has. Some of those services may be missing or diff --git a/src/main/kotlin/core/testing/InMemoryMessagingNetwork.kt b/src/main/kotlin/core/testing/InMemoryMessagingNetwork.kt index 537923be40..9433e5828b 100644 --- a/src/main/kotlin/core/testing/InMemoryMessagingNetwork.kt +++ b/src/main/kotlin/core/testing/InMemoryMessagingNetwork.kt @@ -10,6 +10,7 @@ import core.node.NodeInfo import core.node.services.DummyTimestampingAuthority import core.node.services.NodeTimestamperService import core.node.services.ServiceType +import core.node.services.TimestamperService import core.utilities.loggerFor import rx.Observable import rx.subjects.PublishSubject @@ -151,7 +152,7 @@ class InMemoryMessagingNetwork { val (handle, builder) = createNode(manuallyPumped) val node = builder.start().get() NodeTimestamperService(node, DummyTimestampingAuthority.identity, DummyTimestampingAuthority.key) - timestampingAdvert = NodeInfo(handle, DummyTimestampingAuthority.identity, advertisedServices = setOf(ServiceType.Timestamping)) + timestampingAdvert = NodeInfo(handle, DummyTimestampingAuthority.identity, setOf(TimestamperService.Type)) return Pair(timestampingAdvert!!, node) } diff --git a/src/main/kotlin/core/testing/MockNode.kt b/src/main/kotlin/core/testing/MockNode.kt index 5606510b0d..f7ecdd317b 100644 --- a/src/main/kotlin/core/testing/MockNode.kt +++ b/src/main/kotlin/core/testing/MockNode.kt @@ -11,6 +11,7 @@ import core.node.NodeInfo import core.node.PhysicalLocation import core.node.services.FixedIdentityService import core.node.services.ServiceType +import core.node.services.TimestamperService import core.utilities.loggerFor import org.slf4j.Logger import java.nio.file.Files @@ -131,7 +132,7 @@ class MockNetwork(private val threadPerNode: Boolean = false, fun createTwoNodes(nodeFactory: Factory = defaultFactory): Pair { require(nodes.isEmpty()) return Pair( - createNode(null, -1, nodeFactory, setOf(ServiceType.Timestamping)), + createNode(null, -1, nodeFactory, setOf(TimestamperService.Type)), createNode(nodes[0].info, -1, nodeFactory) ) } diff --git a/src/main/kotlin/demos/IRSDemo.kt b/src/main/kotlin/demos/IRSDemo.kt index 687dae0ecd..e5786d515d 100644 --- a/src/main/kotlin/demos/IRSDemo.kt +++ b/src/main/kotlin/demos/IRSDemo.kt @@ -9,7 +9,9 @@ import core.node.NodeConfiguration import core.node.NodeConfigurationFromConfig import core.node.NodeInfo import core.node.services.ArtemisMessagingService +import core.node.services.NodeInterestRates import core.node.services.ServiceType +import core.node.services.TimestamperService import core.testing.MockNetworkMapCache import core.serialization.deserialize import core.utilities.BriefLogFormatter @@ -72,7 +74,7 @@ fun main(args: Array) { null } else { try { - nodeInfo(options.valueOf(timestamperNetAddr), options.valueOf(timestamperIdentityFile), setOf(ServiceType.Timestamping)) + nodeInfo(options.valueOf(timestamperNetAddr), options.valueOf(timestamperIdentityFile), setOf(TimestamperService.Type)) } catch (e: Exception) { null } @@ -83,7 +85,7 @@ fun main(args: Array) { null } else { try { - nodeInfo(options.valueOf(rateOracleNetAddr), options.valueOf(rateOracleIdentityFile), setOf(ServiceType.RatesOracle)) + nodeInfo(options.valueOf(rateOracleNetAddr), options.valueOf(rateOracleIdentityFile), setOf(NodeInterestRates.Type)) } catch (e: Exception) { null } @@ -128,7 +130,7 @@ fun nodeInfo(hostAndPortString: String, identityFile: String, advertisedServices val addr = HostAndPort.fromString(hostAndPortString).withDefaultPort(Node.DEFAULT_PORT) val path = Paths.get(identityFile) val party = Files.readAllBytes(path).deserialize(includeClassName = true) - return NodeInfo(ArtemisMessagingService.makeRecipient(addr), party, advertisedServices = advertisedServices) + return NodeInfo(ArtemisMessagingService.makeRecipient(addr), party, advertisedServices) } 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") throw e diff --git a/src/test/kotlin/core/messaging/AttachmentTests.kt b/src/test/kotlin/core/messaging/AttachmentTests.kt index 887a9fbbad..28d9a1b403 100644 --- a/src/test/kotlin/core/messaging/AttachmentTests.kt +++ b/src/test/kotlin/core/messaging/AttachmentTests.kt @@ -6,7 +6,7 @@ import core.crypto.sha256 import core.node.NodeConfiguration import core.node.NodeInfo import core.node.services.NodeAttachmentService -import core.node.services.ServiceType +import core.node.services.TimestamperService import core.serialization.OpaqueBytes import core.testing.MockNetwork import core.testutils.rootCauseExceptions @@ -96,7 +96,7 @@ class AttachmentTests { } } } - }, advertisedServices = setOf(ServiceType.Timestamping)) + }, advertisedServices = setOf(TimestamperService.Type)) val n1 = network.createNode(n0.info) // Insert an attachment into node zero's store directly.