Network map redesign: Change field types in NodeInfo, move away messaging data from NodeInfo (#921)

* First stage of changing fields in NodeInfo.

Part of work related to NetworkMapService upgrade. Create slots for
multiple IP addresses and legalIdentities per node.

* NodeInfo stores HostAndPort.

Move information specific to messaging layer away from NodeInfo.
Only HostAndPort addresses are stored. Add peer name - peer handle
mapping to MockNetwork to reflect that change.
This commit is contained in:
Katarzyna Streich 2017-06-27 18:14:51 +01:00 committed by GitHub
parent 4139cf497d
commit 58da76c052
43 changed files with 167 additions and 144 deletions

View File

@ -1,12 +1,11 @@
package net.corda.core.node package net.corda.core.node
import com.google.common.net.HostAndPort
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate import net.corda.core.identity.PartyAndCertificate
import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.node.services.ServiceInfo import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.ServiceType import net.corda.core.node.services.ServiceType
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import org.bouncycastle.cert.X509CertificateHolder
/** /**
* Information for an advertised service including the service specific identity information. * Information for an advertised service including the service specific identity information.
@ -18,16 +17,17 @@ data class ServiceEntry(val info: ServiceInfo, val identity: PartyAndCertificate
/** /**
* Info about a network node that acts on behalf of some form of contract party. * Info about a network node that acts on behalf of some form of contract party.
*/ */
// TODO We currently don't support multi-IP/multi-identity nodes, we only left slots in the data structures.
@CordaSerializable @CordaSerializable
data class NodeInfo(val address: SingleMessageRecipient, data class NodeInfo(val addresses: List<HostAndPort>,
val legalIdentityAndCert: PartyAndCertificate, val legalIdentityAndCert: PartyAndCertificate, //TODO This field will be removed in future PR which gets rid of services.
val legalIdentitiesAndCerts: Set<PartyAndCertificate>,
val platformVersion: Int, val platformVersion: Int,
var advertisedServices: List<ServiceEntry> = emptyList(), var advertisedServices: List<ServiceEntry> = emptyList(),
val physicalLocation: PhysicalLocation? = null) { val worldMapLocation: WorldMapLocation? = null) {
init { init {
require(advertisedServices.none { it.identity == legalIdentityAndCert }) { "Service identities must be different from node legal identity" } require(advertisedServices.none { it.identity == legalIdentityAndCert }) { "Service identities must be different from node legal identity" }
} }
val legalIdentity: Party val legalIdentity: Party
get() = legalIdentityAndCert.party get() = legalIdentityAndCert.party
val notaryIdentity: Party val notaryIdentity: Party
@ -35,7 +35,4 @@ data class NodeInfo(val address: SingleMessageRecipient,
fun serviceIdentities(type: ServiceType): List<Party> { fun serviceIdentities(type: ServiceType): List<Party> {
return advertisedServices.filter { it.info.type.isSubTypeOf(type) }.map { it.identity.party } return advertisedServices.filter { it.info.type.isSubTypeOf(type) }.map { it.identity.party }
} }
fun servideIdentitiesAndCert(type: ServiceType): List<PartyAndCertificate> {
return advertisedServices.filter { it.info.type.isSubTypeOf(type) }.map { it.identity }
}
} }

View File

@ -43,15 +43,15 @@ data class WorldCoordinate(val latitude: Double, val longitude: Double) {
* The [countryCode] field is a two letter ISO country code. * The [countryCode] field is a two letter ISO country code.
*/ */
@CordaSerializable @CordaSerializable
data class PhysicalLocation(val coordinate: WorldCoordinate, val description: String, val countryCode: String) data class WorldMapLocation(val coordinate: WorldCoordinate, val description: String, val countryCode: String)
/** /**
* A simple lookup table of city names to their coordinates. Lookups are case insensitive. * A simple lookup table of city names to their coordinates. Lookups are case insensitive.
*/ */
object CityDatabase { object CityDatabase {
private val matcher = Regex("^([a-zA-Z- ]*) \\((..)\\)$") private val matcher = Regex("^([a-zA-Z- ]*) \\((..)\\)$")
private val caseInsensitiveLookups = HashMap<String, PhysicalLocation>() private val caseInsensitiveLookups = HashMap<String, WorldMapLocation>()
val cityMap = HashMap<String, PhysicalLocation>() val cityMap = HashMap<String, WorldMapLocation>()
init { init {
javaClass.getResourceAsStream("cities.txt").bufferedReader().useLines { lines -> javaClass.getResourceAsStream("cities.txt").bufferedReader().useLines { lines ->
@ -60,7 +60,7 @@ object CityDatabase {
val (name, lng, lat) = line.split('\t') val (name, lng, lat) = line.split('\t')
val matchResult = matcher.matchEntire(name) ?: throw Exception("Could not parse line: $line") val matchResult = matcher.matchEntire(name) ?: throw Exception("Could not parse line: $line")
val (city, country) = matchResult.destructured val (city, country) = matchResult.destructured
val location = PhysicalLocation(WorldCoordinate(lat.toDouble(), lng.toDouble()), city, country) val location = WorldMapLocation(WorldCoordinate(lat.toDouble(), lng.toDouble()), city, country)
caseInsensitiveLookups[city.toLowerCase()] = location caseInsensitiveLookups[city.toLowerCase()] = location
cityMap[city] = location cityMap[city] = location
} }

View File

@ -69,7 +69,7 @@ class AttachmentSerializationTest {
fun setUp() { fun setUp() {
mockNet = MockNetwork() mockNet = MockNetwork()
server = mockNet.createNode(advertisedServices = ServiceInfo(NetworkMapService.type)) server = mockNet.createNode(advertisedServices = ServiceInfo(NetworkMapService.type))
client = mockNet.createNode(server.info.address) client = mockNet.createNode(server.network.myAddress)
client.disableDBCloseOnStop() // Otherwise the in-memory database may disappear (taking the checkpoint with it) while we reboot the client. client.disableDBCloseOnStop() // Otherwise the in-memory database may disappear (taking the checkpoint with it) while we reboot the client.
mockNet.runNetwork() mockNet.runNetwork()
} }
@ -149,7 +149,7 @@ class AttachmentSerializationTest {
private fun rebootClientAndGetAttachmentContent(checkAttachmentsOnLoad: Boolean = true): String { private fun rebootClientAndGetAttachmentContent(checkAttachmentsOnLoad: Boolean = true): String {
client.stop() client.stop()
client = mockNet.createNode(server.info.address, client.id, object : MockNetwork.Factory { client = mockNet.createNode(server.network.myAddress, client.id, object : MockNetwork.Factory {
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, entropyRoot: BigInteger): MockNetwork.MockNode { override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, entropyRoot: BigInteger): MockNetwork.MockNode {
return object : MockNetwork.MockNode(config, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) { return object : MockNetwork.MockNode(config, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) {
override fun startMessagingService(rpcOps: RPCOps) { override fun startMessagingService(rpcOps: RPCOps) {

View File

@ -27,8 +27,8 @@ class TxKeyFlowTests {
// Set up values we'll need // Set up values we'll need
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = mockNet.createPartyNode(notaryNode.info.address, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.info.address, BOB.name) val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val alice: Party = aliceNode.services.myInfo.legalIdentity val alice: Party = aliceNode.services.myInfo.legalIdentity
val bob: Party = bobNode.services.myInfo.legalIdentity val bob: Party = bobNode.services.myInfo.legalIdentity
aliceNode.services.identityService.registerIdentity(bobNode.info.legalIdentityAndCert) aliceNode.services.identityService.registerIdentity(bobNode.info.legalIdentityAndCert)

View File

@ -6,6 +6,12 @@ from the previous milestone release.
UNRELEASED UNRELEASED
---------- ----------
* Changes in ``NodeInfo``:
* ``PhysicalLocation`` was renamed to ``WorldMapLocation`` to emphasise that it doesn't need to map to a truly physical
location of the node server.
* Slots for multiple IP addresses and ``legalIdentitiesAndCert``s were introduced. Addresses are no longer of type
``SingleMessageRecipient``, but of ``HostAndPort``.
Milestone 13 Milestone 13
---------- ----------

View File

@ -12,8 +12,6 @@ import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatedBy import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.InitiatingFlow import net.corda.core.flows.InitiatingFlow
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.PluginServiceHub
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.node.services.unconsumedStates import net.corda.core.node.services.unconsumedStates
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable

View File

@ -31,8 +31,8 @@ class FxTransactionBuildTutorialTest {
legalName = DUMMY_NOTARY.name, legalName = DUMMY_NOTARY.name,
overrideServices = mapOf(notaryService to DUMMY_NOTARY_KEY), overrideServices = mapOf(notaryService to DUMMY_NOTARY_KEY),
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), notaryService)) advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), notaryService))
nodeA = mockNet.createPartyNode(notaryNode.info.address) nodeA = mockNet.createPartyNode(notaryNode.network.myAddress)
nodeB = mockNet.createPartyNode(notaryNode.info.address) nodeB = mockNet.createPartyNode(notaryNode.network.myAddress)
nodeB.registerInitiatedFlow(ForeignExchangeRemoteFlow::class.java) nodeB.registerInitiatedFlow(ForeignExchangeRemoteFlow::class.java)
} }

View File

@ -43,8 +43,8 @@ class WorkflowTransactionBuildTutorialTest {
legalName = DUMMY_NOTARY.name, legalName = DUMMY_NOTARY.name,
overrideServices = mapOf(Pair(notaryService, DUMMY_NOTARY_KEY)), overrideServices = mapOf(Pair(notaryService, DUMMY_NOTARY_KEY)),
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), notaryService)) advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), notaryService))
nodeA = mockNet.createPartyNode(notaryNode.info.address) nodeA = mockNet.createPartyNode(notaryNode.network.myAddress)
nodeB = mockNet.createPartyNode(notaryNode.info.address) nodeB = mockNet.createPartyNode(notaryNode.network.myAddress)
nodeA.registerInitiatedFlow(RecordCompletionFlow::class.java) nodeA.registerInitiatedFlow(RecordCompletionFlow::class.java)
} }

View File

@ -37,8 +37,8 @@ class IssuerFlowTest {
fun start() { fun start() {
mockNet = MockNetwork(threadPerNode = true) mockNet = MockNetwork(threadPerNode = true)
notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
bankOfCordaNode = mockNet.createPartyNode(notaryNode.info.address, BOC.name) bankOfCordaNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
bankClientNode = mockNet.createPartyNode(notaryNode.info.address, MEGA_CORP.name) bankClientNode = mockNet.createPartyNode(notaryNode.network.myAddress, MEGA_CORP.name)
} }
@After @After

View File

@ -6,6 +6,8 @@ import net.corda.core.crypto.toBase58String
import net.corda.core.messaging.MessageRecipientGroup import net.corda.core.messaging.MessageRecipientGroup
import net.corda.core.messaging.MessageRecipients import net.corda.core.messaging.MessageRecipients
import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.node.NodeInfo
import net.corda.core.node.services.ServiceType
import net.corda.core.read import net.corda.core.read
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.SingletonSerializeAsToken
@ -34,18 +36,6 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
const val P2P_QUEUE = "p2p.inbound" const val P2P_QUEUE = "p2p.inbound"
const val NOTIFICATIONS_ADDRESS = "${INTERNAL_PREFIX}activemq.notifications" const val NOTIFICATIONS_ADDRESS = "${INTERNAL_PREFIX}activemq.notifications"
const val NETWORK_MAP_QUEUE = "${INTERNAL_PREFIX}networkmap" const val NETWORK_MAP_QUEUE = "${INTERNAL_PREFIX}networkmap"
/**
* Assuming the passed in target address is actually an ArtemisAddress will extract the host and port of the node. This should
* only be used in unit tests and the internals of the messaging services to keep addressing opaque for the future.
* N.B. Marked as JvmStatic to allow use in the inherited classes.
*/
@JvmStatic
@VisibleForTesting
fun toHostAndPort(target: MessageRecipients): HostAndPort {
val addr = target as? ArtemisMessagingComponent.ArtemisPeerAddress ?: throw IllegalArgumentException("Not an Artemis address")
return addr.hostAndPort
}
} }
interface ArtemisAddress : MessageRecipients { interface ArtemisAddress : MessageRecipients {
@ -57,7 +47,7 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
} }
@CordaSerializable @CordaSerializable
data class NetworkMapAddress(override val hostAndPort: HostAndPort) : SingleMessageRecipient, ArtemisPeerAddress { data class NetworkMapAddress(override val hostAndPort: HostAndPort) : ArtemisPeerAddress {
override val queueName: String get() = NETWORK_MAP_QUEUE override val queueName: String get() = NETWORK_MAP_QUEUE
} }
@ -116,4 +106,12 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
KeyStore.getInstance("JKS").load(it, config.trustStorePassword.toCharArray()) KeyStore.getInstance("JKS").load(it, config.trustStorePassword.toCharArray())
} }
} }
fun getArtemisPeerAddress(nodeInfo: NodeInfo): ArtemisPeerAddress {
return if (nodeInfo.advertisedServices.any { it.info.type == ServiceType.networkMap }) {
NetworkMapAddress(nodeInfo.addresses.first())
} else {
NodeAddress.asPeer(nodeInfo.legalIdentity.owningKey, nodeInfo.addresses.first())
}
}
} }

View File

@ -50,7 +50,7 @@ class BFTNotaryServiceTests {
val notaryClusterAddresses = replicaIds.map { HostAndPort.fromParts("localhost", 11000 + it * 10) } val notaryClusterAddresses = replicaIds.map { HostAndPort.fromParts("localhost", 11000 + it * 10) }
replicaIds.forEach { replicaId -> replicaIds.forEach { replicaId ->
mockNet.createNode( mockNet.createNode(
node.info.address, node.network.myAddress,
advertisedServices = bftNotaryService, advertisedServices = bftNotaryService,
configOverrides = { configOverrides = {
whenever(it.bftReplicaId).thenReturn(replicaId) whenever(it.bftReplicaId).thenReturn(replicaId)

View File

@ -16,6 +16,7 @@ import net.corda.node.services.network.NetworkMapService
import net.corda.node.services.network.NetworkMapService.RegistrationRequest import net.corda.node.services.network.NetworkMapService.RegistrationRequest
import net.corda.node.services.network.NodeRegistration import net.corda.node.services.network.NodeRegistration
import net.corda.node.utilities.AddOrRemove import net.corda.node.utilities.AddOrRemove
import net.corda.testing.MOCK_HOST_AND_PORT
import net.corda.testing.MOCK_VERSION_INFO import net.corda.testing.MOCK_VERSION_INFO
import net.corda.testing.node.NodeBasedTest import net.corda.testing.node.NodeBasedTest
import net.corda.testing.node.SimpleNode import net.corda.testing.node.SimpleNode
@ -69,7 +70,7 @@ class P2PSecurityTest : NodeBasedTest() {
private fun SimpleNode.registerWithNetworkMap(registrationName: X500Name): ListenableFuture<NetworkMapService.RegistrationResponse> { private fun SimpleNode.registerWithNetworkMap(registrationName: X500Name): ListenableFuture<NetworkMapService.RegistrationResponse> {
val legalIdentity = getTestPartyAndCertificate(registrationName, identity.public) val legalIdentity = getTestPartyAndCertificate(registrationName, identity.public)
val nodeInfo = NodeInfo(network.myAddress, legalIdentity, MOCK_VERSION_INFO.platformVersion) val nodeInfo = NodeInfo(listOf(MOCK_HOST_AND_PORT), legalIdentity, setOf(legalIdentity), MOCK_VERSION_INFO.platformVersion)
val registration = NodeRegistration(nodeInfo, System.currentTimeMillis(), AddOrRemove.ADD, Instant.MAX) val registration = NodeRegistration(nodeInfo, System.currentTimeMillis(), AddOrRemove.ADD, Instant.MAX)
val request = RegistrationRequest(registration.toWire(keyService, identity.public), network.myAddress) val request = RegistrationRequest(registration.toWire(keyService, identity.public), network.myAddress)
return network.sendRequest<NetworkMapService.RegistrationResponse>(NetworkMapService.REGISTER_TOPIC, request, networkMapNode.network.myAddress) return network.sendRequest<NetworkMapService.RegistrationResponse>(NetworkMapService.REGISTER_TOPIC, request, networkMapNode.network.myAddress)

View File

@ -3,6 +3,7 @@ package net.corda.node.internal
import com.codahale.metrics.MetricRegistry import com.codahale.metrics.MetricRegistry
import com.google.common.annotations.VisibleForTesting import com.google.common.annotations.VisibleForTesting
import com.google.common.collect.MutableClassToInstanceMap import com.google.common.collect.MutableClassToInstanceMap
import com.google.common.net.HostAndPort
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import com.google.common.util.concurrent.MoreExecutors import com.google.common.util.concurrent.MoreExecutors
import com.google.common.util.concurrent.SettableFuture import com.google.common.util.concurrent.SettableFuture
@ -58,6 +59,7 @@ import net.corda.node.utilities.AddOrRemove.ADD
import net.corda.node.utilities.AffinityExecutor import net.corda.node.utilities.AffinityExecutor
import net.corda.node.utilities.configureDatabase import net.corda.node.utilities.configureDatabase
import net.corda.node.utilities.transaction import net.corda.node.utilities.transaction
import net.corda.nodeapi.ArtemisMessagingComponent
import org.apache.activemq.artemis.utils.ReusableLatch import org.apache.activemq.artemis.utils.ReusableLatch
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name
import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.Database
@ -158,7 +160,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
} }
} }
open fun findMyLocation(): PhysicalLocation? { open fun findMyLocation(): WorldMapLocation? {
return configuration.myLegalName.locationOrNull?.let { CityDatabase[it] } return configuration.myLegalName.locationOrNull?.let { CityDatabase[it] }
} }
@ -548,7 +550,9 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
private fun makeInfo(): NodeInfo { private fun makeInfo(): NodeInfo {
val advertisedServiceEntries = makeServiceEntries() val advertisedServiceEntries = makeServiceEntries()
val legalIdentity = obtainLegalIdentity() val legalIdentity = obtainLegalIdentity()
return NodeInfo(network.myAddress, legalIdentity, platformVersion, advertisedServiceEntries, findMyLocation()) val allIdentitiesSet = advertisedServiceEntries.map { it.identity }.toSet() + legalIdentity
val addresses = myAddresses() // TODO There is no support for multiple IP addresses yet.
return NodeInfo(addresses, legalIdentity, allIdentitiesSet, platformVersion, advertisedServiceEntries, findMyLocation())
} }
/** /**
@ -641,7 +645,8 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
require(networkMapAddress != null || NetworkMapService.type in advertisedServices.map { it.type }) { require(networkMapAddress != null || NetworkMapService.type in advertisedServices.map { it.type }) {
"Initial network map address must indicate a node that provides a network map service" "Initial network map address must indicate a node that provides a network map service"
} }
val address = networkMapAddress ?: info.address val address: SingleMessageRecipient = networkMapAddress ?:
network.getAddressOfParty(PartyInfo.Node(info)) as SingleMessageRecipient
// Register for updates, even if we're the one running the network map. // Register for updates, even if we're the one running the network map.
return sendNetworkMapRegistration(address).flatMap { (error) -> return sendNetworkMapRegistration(address).flatMap { (error) ->
check(error == null) { "Unable to register with the network map service: $error" } check(error == null) { "Unable to register with the network map service: $error" }
@ -660,6 +665,9 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
return network.sendRequest(NetworkMapService.REGISTER_TOPIC, request, networkMapAddress) return network.sendRequest(NetworkMapService.REGISTER_TOPIC, request, networkMapAddress)
} }
/** Return list of node's addresses. It's overridden in MockNetwork as we don't have real addresses for MockNodes. */
protected abstract fun myAddresses(): List<HostAndPort>
/** This is overriden by the mock node implementation to enable operation without any network map service */ /** This is overriden by the mock node implementation to enable operation without any network map service */
protected open fun noNetworkMapConfigured(): ListenableFuture<Unit> { protected open fun noNetworkMapConfigured(): ListenableFuture<Unit> {
// TODO: There should be a consistent approach to configuration error exceptions. // TODO: There should be a consistent approach to configuration error exceptions.

View File

@ -32,6 +32,7 @@ import net.corda.node.services.transactions.RaftUniquenessProvider
import net.corda.node.services.transactions.RaftValidatingNotaryService import net.corda.node.services.transactions.RaftValidatingNotaryService
import net.corda.node.utilities.AddressUtils import net.corda.node.utilities.AddressUtils
import net.corda.node.utilities.AffinityExecutor import net.corda.node.utilities.AffinityExecutor
import net.corda.nodeapi.ArtemisMessagingComponent
import net.corda.nodeapi.ArtemisMessagingComponent.Companion.IP_REQUEST_PREFIX import net.corda.nodeapi.ArtemisMessagingComponent.Companion.IP_REQUEST_PREFIX
import net.corda.nodeapi.ArtemisMessagingComponent.Companion.PEER_USER import net.corda.nodeapi.ArtemisMessagingComponent.Companion.PEER_USER
import net.corda.nodeapi.ArtemisMessagingComponent.NetworkMapAddress import net.corda.nodeapi.ArtemisMessagingComponent.NetworkMapAddress
@ -274,6 +275,11 @@ open class Node(override val configuration: FullNodeConfiguration,
} }
} }
override fun myAddresses(): List<HostAndPort> {
val address = network.myAddress as ArtemisMessagingComponent.ArtemisPeerAddress
return listOf(address.hostAndPort)
}
/** /**
* If the node is persisting to an embedded H2 database, then expose this via TCP with a JDBC URL of the form: * If the node is persisting to an embedded H2 database, then expose this via TCP with a JDBC URL of the form:
* jdbc:h2:tcp://<host>:<port>/node * jdbc:h2:tcp://<host>:<port>/node

View File

@ -1,6 +1,7 @@
package net.corda.node.services.api package net.corda.node.services.api
import com.google.common.annotations.VisibleForTesting import com.google.common.annotations.VisibleForTesting
import com.google.common.net.HostAndPort
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import net.corda.core.flows.FlowInitiator import net.corda.core.flows.FlowInitiator
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic

View File

@ -298,12 +298,8 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
fun deployBridgeToPeer(nodeInfo: NodeInfo) { fun deployBridgeToPeer(nodeInfo: NodeInfo) {
log.debug("Deploying bridge for $queueName to $nodeInfo") log.debug("Deploying bridge for $queueName to $nodeInfo")
val address = nodeInfo.address val address = nodeInfo.addresses.first() // TODO Load balancing.
if (address is ArtemisPeerAddress) { deployBridge(queueName, address, nodeInfo.legalIdentity.name)
deployBridge(queueName, address.hostAndPort, nodeInfo.legalIdentity.name)
} else {
log.error("Don't know how to deal with $address for queue $queueName")
}
} }
when { when {
@ -342,7 +338,7 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
*/ */
private fun updateBridgesOnNetworkChange(change: MapChange) { private fun updateBridgesOnNetworkChange(change: MapChange) {
fun gatherAddresses(node: NodeInfo): Sequence<ArtemisPeerAddress> { fun gatherAddresses(node: NodeInfo): Sequence<ArtemisPeerAddress> {
val peerAddress = node.address as ArtemisPeerAddress val peerAddress = getArtemisPeerAddress(node)
val addresses = mutableListOf(peerAddress) val addresses = mutableListOf(peerAddress)
node.advertisedServices.mapTo(addresses) { NodeAddress.asService(it.identity.owningKey, peerAddress.hostAndPort) } node.advertisedServices.mapTo(addresses) { NodeAddress.asService(it.identity.owningKey, peerAddress.hostAndPort) }
return addresses.asSequence() return addresses.asSequence()

View File

@ -564,11 +564,10 @@ class NodeMessagingClient(override val config: NodeConfiguration,
} }
} }
override fun getAddressOfParty(partyInfo: PartyInfo): MessageRecipients { override fun getAddressOfParty(partyInfo: PartyInfo): MessageRecipients {
return when (partyInfo) { return when (partyInfo) {
is PartyInfo.Node -> partyInfo.node.address is PartyInfo.Node -> getArtemisPeerAddress(partyInfo.node)
is PartyInfo.Service -> ArtemisMessagingComponent.ServiceAddress(partyInfo.service.identity.owningKey) is PartyInfo.Service -> ServiceAddress(partyInfo.service.identity.owningKey)
} }
} }
} }

View File

@ -134,7 +134,9 @@ open class InMemoryNetworkMapCache : SingletonSerializeAsToken(), NetworkMapCach
override fun deregisterForUpdates(network: MessagingService, service: NodeInfo): ListenableFuture<Unit> { override fun deregisterForUpdates(network: MessagingService, service: NodeInfo): ListenableFuture<Unit> {
// Fetch the network map and register for updates at the same time // Fetch the network map and register for updates at the same time
val req = NetworkMapService.SubscribeRequest(false, network.myAddress) val req = NetworkMapService.SubscribeRequest(false, network.myAddress)
val future = network.sendRequest<SubscribeResponse>(NetworkMapService.SUBSCRIPTION_TOPIC, req, service.address).map { // `network.getAddressOfParty(partyInfo)` is a work-around for MockNetwork and InMemoryMessaging to get rid of SingleMessageRecipient in NodeInfo.
val address = network.getAddressOfParty(PartyInfo.Node(service))
val future = network.sendRequest<SubscribeResponse>(NetworkMapService.SUBSCRIPTION_TOPIC, req, address).map {
if (it.confirmed) Unit else throw NetworkCacheError.DeregistrationFailed() if (it.confirmed) Unit else throw NetworkCacheError.DeregistrationFailed()
} }
_registrationFuture.setFuture(future) _registrationFuture.setFuture(future)

View File

@ -273,11 +273,11 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal,
// subscribers // subscribers
when (change.type) { when (change.type) {
ADD -> { ADD -> {
logger.info("Added node ${node.address} to network map") logger.info("Added node ${node.addresses} to network map")
services.networkMapCache.addNode(change.node) services.networkMapCache.addNode(change.node)
} }
REMOVE -> { REMOVE -> {
logger.info("Removed node ${node.address} from network map") logger.info("Removed node ${node.addresses} from network map")
services.networkMapCache.removeNode(change.node) services.networkMapCache.removeNode(change.node)
} }
} }

View File

@ -59,8 +59,8 @@ class CordaRPCOpsImplTest {
fun setup() { fun setup() {
mockNet = MockNetwork() mockNet = MockNetwork()
val networkMap = mockNet.createNode(advertisedServices = ServiceInfo(NetworkMapService.type)) val networkMap = mockNet.createNode(advertisedServices = ServiceInfo(NetworkMapService.type))
aliceNode = mockNet.createNode(networkMapAddress = networkMap.info.address) aliceNode = mockNet.createNode(networkMapAddress = networkMap.network.myAddress)
notaryNode = mockNet.createNode(advertisedServices = ServiceInfo(SimpleNotaryService.type), networkMapAddress = networkMap.info.address) notaryNode = mockNet.createNode(advertisedServices = ServiceInfo(SimpleNotaryService.type), networkMapAddress = networkMap.network.myAddress)
rpc = CordaRPCOpsImpl(aliceNode.services, aliceNode.smm, aliceNode.database) rpc = CordaRPCOpsImpl(aliceNode.services, aliceNode.smm, aliceNode.database)
CURRENT_RPC_CONTEXT.set(RpcContext(User("user", "pwd", permissions = setOf( CURRENT_RPC_CONTEXT.set(RpcContext(User("user", "pwd", permissions = setOf(
startFlowPermission<CashIssueFlow>(), startFlowPermission<CashIssueFlow>(),

View File

@ -114,7 +114,7 @@ class AttachmentTests {
} }
} }
}, true, null, null, ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type)) }, true, null, null, ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type))
val n1 = mockNet.createNode(n0.info.address) val n1 = mockNet.createNode(n0.network.myAddress)
val attachment = fakeAttachment() val attachment = fakeAttachment()
// Insert an attachment into node zero's store directly. // Insert an attachment into node zero's store directly.

View File

@ -34,15 +34,15 @@ class InMemoryMessagingTests {
@Test @Test
fun basics() { fun basics() {
val node1 = mockNet.createNode(advertisedServices = ServiceInfo(NetworkMapService.type)) val node1 = mockNet.createNode(advertisedServices = ServiceInfo(NetworkMapService.type))
val node2 = mockNet.createNode(networkMapAddress = node1.info.address) val node2 = mockNet.createNode(networkMapAddress = node1.network.myAddress)
val node3 = mockNet.createNode(networkMapAddress = node1.info.address) val node3 = mockNet.createNode(networkMapAddress = node1.network.myAddress)
val bits = "test-content".toByteArray() val bits = "test-content".toByteArray()
var finalDelivery: Message? = null var finalDelivery: Message? = null
with(node2) { with(node2) {
node2.network.addMessageHandler { msg, _ -> node2.network.addMessageHandler { msg, _ ->
node2.network.send(msg, node3.info.address) node2.network.send(msg, node3.network.myAddress)
} }
} }
@ -53,7 +53,7 @@ class InMemoryMessagingTests {
} }
// Node 1 sends a message and it should end up in finalDelivery, after we run the network // Node 1 sends a message and it should end up in finalDelivery, after we run the network
node1.network.send(node1.network.createMessage("test.topic", DEFAULT_SESSION_ID, bits), node2.info.address) node1.network.send(node1.network.createMessage("test.topic", DEFAULT_SESSION_ID, bits), node2.network.myAddress)
mockNet.runNetwork(rounds = 1) mockNet.runNetwork(rounds = 1)
@ -63,8 +63,8 @@ class InMemoryMessagingTests {
@Test @Test
fun broadcast() { fun broadcast() {
val node1 = mockNet.createNode(advertisedServices = ServiceInfo(NetworkMapService.type)) val node1 = mockNet.createNode(advertisedServices = ServiceInfo(NetworkMapService.type))
val node2 = mockNet.createNode(networkMapAddress = node1.info.address) val node2 = mockNet.createNode(networkMapAddress = node1.network.myAddress)
val node3 = mockNet.createNode(networkMapAddress = node1.info.address) val node3 = mockNet.createNode(networkMapAddress = node1.network.myAddress)
val bits = "test-content".toByteArray() val bits = "test-content".toByteArray()
@ -82,7 +82,7 @@ class InMemoryMessagingTests {
@Test @Test
fun `skip unhandled messages`() { fun `skip unhandled messages`() {
val node1 = mockNet.createNode(advertisedServices = ServiceInfo(NetworkMapService.type)) val node1 = mockNet.createNode(advertisedServices = ServiceInfo(NetworkMapService.type))
val node2 = mockNet.createNode(networkMapAddress = node1.info.address) val node2 = mockNet.createNode(networkMapAddress = node1.network.myAddress)
var received: Int = 0 var received: Int = 0
node1.network.addMessageHandler("valid_message") { _, _ -> node1.network.addMessageHandler("valid_message") { _, _ ->

View File

@ -127,8 +127,8 @@ class TwoPartyTradeFlowTests {
ledger { ledger {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = mockNet.createPartyNode(notaryNode.info.address, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.info.address, BOB.name) val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
aliceNode.disableDBCloseOnStop() aliceNode.disableDBCloseOnStop()
bobNode.disableDBCloseOnStop() bobNode.disableDBCloseOnStop()
@ -173,13 +173,13 @@ class TwoPartyTradeFlowTests {
fun `shutdown and restore`() { fun `shutdown and restore`() {
ledger { ledger {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = mockNet.createPartyNode(notaryNode.info.address, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
var bobNode = mockNet.createPartyNode(notaryNode.info.address, BOB.name) var bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
aliceNode.disableDBCloseOnStop() aliceNode.disableDBCloseOnStop()
bobNode.disableDBCloseOnStop() bobNode.disableDBCloseOnStop()
val bobAddr = bobNode.network.myAddress as InMemoryMessagingNetwork.PeerHandle val bobAddr = bobNode.network.myAddress as InMemoryMessagingNetwork.PeerHandle
val networkMapAddr = notaryNode.info.address val networkMapAddr = notaryNode.network.myAddress
mockNet.runNetwork() // Clear network map registration messages mockNet.runNetwork() // Clear network map registration messages
@ -291,8 +291,8 @@ class TwoPartyTradeFlowTests {
@Test @Test
fun `check dependencies of sale asset are resolved`() { fun `check dependencies of sale asset are resolved`() {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = makeNodeWithTracking(notaryNode.info.address, ALICE.name) val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
val bobNode = makeNodeWithTracking(notaryNode.info.address, BOB.name) val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
ledger(aliceNode.services) { ledger(aliceNode.services) {
@ -390,8 +390,8 @@ class TwoPartyTradeFlowTests {
@Test @Test
fun `track works`() { fun `track works`() {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = makeNodeWithTracking(notaryNode.info.address, ALICE.name) val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
val bobNode = makeNodeWithTracking(notaryNode.info.address, BOB.name) val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
ledger(aliceNode.services) { ledger(aliceNode.services) {
@ -528,8 +528,8 @@ class TwoPartyTradeFlowTests {
expectedMessageSubstring: String expectedMessageSubstring: String
) { ) {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = mockNet.createPartyNode(notaryNode.info.address, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.info.address, BOB.name) val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val issuer = MEGA_CORP.ref(1, 2, 3) val issuer = MEGA_CORP.ref(1, 2, 3)
val bobsBadCash = bobNode.database.transaction { val bobsBadCash = bobNode.database.transaction {

View File

@ -37,9 +37,9 @@ class NotaryChangeTests {
oldNotaryNode = mockNet.createNode( oldNotaryNode = mockNet.createNode(
legalName = DUMMY_NOTARY.name, legalName = DUMMY_NOTARY.name,
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type))) advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type)))
clientNodeA = mockNet.createNode(networkMapAddress = oldNotaryNode.info.address) clientNodeA = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress)
clientNodeB = mockNet.createNode(networkMapAddress = oldNotaryNode.info.address) clientNodeB = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress)
newNotaryNode = mockNet.createNode(networkMapAddress = oldNotaryNode.info.address, advertisedServices = ServiceInfo(SimpleNotaryService.type)) newNotaryNode = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress, advertisedServices = ServiceInfo(SimpleNotaryService.type))
mockNet.runNetwork() // Clear network map registration messages mockNet.runNetwork() // Clear network map registration messages
} }

View File

@ -94,8 +94,8 @@ class ScheduledFlowTests {
notaryNode = mockNet.createNode( notaryNode = mockNet.createNode(
legalName = DUMMY_NOTARY.name, legalName = DUMMY_NOTARY.name,
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type))) advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type)))
nodeA = mockNet.createNode(notaryNode.info.address, start = false) nodeA = mockNet.createNode(notaryNode.network.myAddress, start = false)
nodeB = mockNet.createNode(notaryNode.info.address, start = false) nodeB = mockNet.createNode(notaryNode.network.myAddress, start = false)
mockNet.startNodes() mockNet.startNodes()
} }

View File

@ -186,8 +186,8 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
} }
private fun MockNode.fetchMap(subscribe: Boolean = false, ifChangedSinceVersion: Int? = null): List<Changed> { private fun MockNode.fetchMap(subscribe: Boolean = false, ifChangedSinceVersion: Int? = null): List<Changed> {
val request = FetchMapRequest(subscribe, ifChangedSinceVersion, info.address) val request = FetchMapRequest(subscribe, ifChangedSinceVersion, network.myAddress)
val response = services.networkService.sendRequest<FetchMapResponse>(FETCH_TOPIC, request, mapServiceNode.info.address) val response = services.networkService.sendRequest<FetchMapResponse>(FETCH_TOPIC, request, mapServiceNode.network.myAddress)
mockNet.runNetwork() mockNet.runNetwork()
return response.getOrThrow().nodes?.map { it.toChanged() } ?: emptyList() return response.getOrThrow().nodes?.map { it.toChanged() } ?: emptyList()
} }
@ -198,8 +198,8 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
} }
private fun MockNode.identityQuery(): NodeInfo? { private fun MockNode.identityQuery(): NodeInfo? {
val request = QueryIdentityRequest(info.legalIdentityAndCert, info.address) val request = QueryIdentityRequest(info.legalIdentityAndCert, network.myAddress)
val response = services.networkService.sendRequest<QueryIdentityResponse>(QUERY_TOPIC, request, mapServiceNode.info.address) val response = services.networkService.sendRequest<QueryIdentityResponse>(QUERY_TOPIC, request, mapServiceNode.network.myAddress)
mockNet.runNetwork() mockNet.runNetwork()
return response.getOrThrow().node return response.getOrThrow().node
} }
@ -216,39 +216,39 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
} }
val expires = Instant.now() + NetworkMapService.DEFAULT_EXPIRATION_PERIOD val expires = Instant.now() + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
val nodeRegistration = NodeRegistration(info, distinctSerial, addOrRemove, expires) val nodeRegistration = NodeRegistration(info, distinctSerial, addOrRemove, expires)
val request = RegistrationRequest(nodeRegistration.toWire(services.keyManagementService, services.legalIdentityKey), info.address) val request = RegistrationRequest(nodeRegistration.toWire(services.keyManagementService, services.legalIdentityKey), network.myAddress)
val response = services.networkService.sendRequest<RegistrationResponse>(REGISTER_TOPIC, request, mapServiceNode.info.address) val response = services.networkService.sendRequest<RegistrationResponse>(REGISTER_TOPIC, request, mapServiceNode.network.myAddress)
mockNet.runNetwork() mockNet.runNetwork()
return response return response
} }
private fun MockNode.subscribe(): List<Update> { private fun MockNode.subscribe(): List<Update> {
val request = SubscribeRequest(true, info.address) val request = SubscribeRequest(true, network.myAddress)
val updates = BlockingArrayQueue<Update>() val updates = BlockingArrayQueue<Update>()
services.networkService.addMessageHandler(PUSH_TOPIC, DEFAULT_SESSION_ID) { message, _ -> services.networkService.addMessageHandler(PUSH_TOPIC, DEFAULT_SESSION_ID) { message, _ ->
updates += message.data.deserialize<Update>() updates += message.data.deserialize<Update>()
} }
val response = services.networkService.sendRequest<SubscribeResponse>(SUBSCRIPTION_TOPIC, request, mapServiceNode.info.address) val response = services.networkService.sendRequest<SubscribeResponse>(SUBSCRIPTION_TOPIC, request, mapServiceNode.network.myAddress)
mockNet.runNetwork() mockNet.runNetwork()
assertThat(response.getOrThrow().confirmed).isTrue() assertThat(response.getOrThrow().confirmed).isTrue()
return updates return updates
} }
private fun MockNode.unsubscribe() { private fun MockNode.unsubscribe() {
val request = SubscribeRequest(false, info.address) val request = SubscribeRequest(false, network.myAddress)
val response = services.networkService.sendRequest<SubscribeResponse>(SUBSCRIPTION_TOPIC, request, mapServiceNode.info.address) val response = services.networkService.sendRequest<SubscribeResponse>(SUBSCRIPTION_TOPIC, request, mapServiceNode.network.myAddress)
mockNet.runNetwork() mockNet.runNetwork()
assertThat(response.getOrThrow().confirmed).isTrue() assertThat(response.getOrThrow().confirmed).isTrue()
} }
private fun MockNode.ackUpdate(mapVersion: Int) { private fun MockNode.ackUpdate(mapVersion: Int) {
val request = UpdateAcknowledge(mapVersion, services.networkService.myAddress) val request = UpdateAcknowledge(mapVersion, services.networkService.myAddress)
services.networkService.send(PUSH_ACK_TOPIC, DEFAULT_SESSION_ID, request, mapServiceNode.info.address) services.networkService.send(PUSH_ACK_TOPIC, DEFAULT_SESSION_ID, request, mapServiceNode.network.myAddress)
mockNet.runNetwork() mockNet.runNetwork()
} }
private fun addNewNodeToNetworkMap(legalName: X500Name): MockNode { private fun addNewNodeToNetworkMap(legalName: X500Name): MockNode {
val node = mockNet.createNode(networkMapAddress = mapServiceNode.info.address, legalName = legalName) val node = mockNet.createNode(networkMapAddress = mapServiceNode.network.myAddress, legalName = legalName)
mockNet.runNetwork() mockNet.runNetwork()
lastSerial = System.currentTimeMillis() lastSerial = System.currentTimeMillis()
return node return node

View File

@ -16,7 +16,7 @@ class InMemoryNetworkMapCacheTest {
@Test @Test
fun registerWithNetwork() { fun registerWithNetwork() {
val (n0, n1) = mockNet.createTwoNodes() val (n0, n1) = mockNet.createTwoNodes()
val future = n1.services.networkMapCache.addMapService(n1.network, n0.info.address, false, null) val future = n1.services.networkMapCache.addMapService(n1.network, n0.network.myAddress, false, null)
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() future.getOrThrow()
} }

View File

@ -81,8 +81,8 @@ class FlowFrameworkTests {
val overrideServices = mapOf(Pair(notaryService, notaryKeyPair)) val overrideServices = mapOf(Pair(notaryService, notaryKeyPair))
// Note that these notaries don't operate correctly as they don't share their state. They are only used for testing // Note that these notaries don't operate correctly as they don't share their state. They are only used for testing
// service addressing. // service addressing.
notary1 = mockNet.createNotaryNode(networkMapAddr = node1.services.myInfo.address, overrideServices = overrideServices, serviceName = notaryService.name) notary1 = mockNet.createNotaryNode(networkMapAddr = node1.network.myAddress, overrideServices = overrideServices, serviceName = notaryService.name)
notary2 = mockNet.createNotaryNode(networkMapAddr = node1.services.myInfo.address, overrideServices = overrideServices, serviceName = notaryService.name) notary2 = mockNet.createNotaryNode(networkMapAddr = node1.network.myAddress, overrideServices = overrideServices, serviceName = notaryService.name)
mockNet.messagingNetwork.receivedMessages.toSessionTransfers().forEach { sessionTransfers += it } mockNet.messagingNetwork.receivedMessages.toSessionTransfers().forEach { sessionTransfers += it }
mockNet.runNetwork() mockNet.runNetwork()
@ -148,7 +148,7 @@ class FlowFrameworkTests {
@Test @Test
fun `flow added before network map does run after init`() { fun `flow added before network map does run after init`() {
val node3 = mockNet.createNode(node1.info.address) //create vanilla node val node3 = mockNet.createNode(node1.network.myAddress) //create vanilla node
val flow = NoOpFlow() val flow = NoOpFlow()
node3.services.startFlow(flow) node3.services.startFlow(flow)
assertEquals(false, flow.flowStarted) // Not started yet as no network activity has been allowed yet assertEquals(false, flow.flowStarted) // Not started yet as no network activity has been allowed yet
@ -158,14 +158,14 @@ class FlowFrameworkTests {
@Test @Test
fun `flow added before network map will be init checkpointed`() { fun `flow added before network map will be init checkpointed`() {
var node3 = mockNet.createNode(node1.info.address) //create vanilla node var node3 = mockNet.createNode(node1.network.myAddress) //create vanilla node
val flow = NoOpFlow() val flow = NoOpFlow()
node3.services.startFlow(flow) node3.services.startFlow(flow)
assertEquals(false, flow.flowStarted) // Not started yet as no network activity has been allowed yet assertEquals(false, flow.flowStarted) // Not started yet as no network activity has been allowed yet
node3.disableDBCloseOnStop() node3.disableDBCloseOnStop()
node3.stop() node3.stop()
node3 = mockNet.createNode(node1.info.address, forcedID = node3.id) node3 = mockNet.createNode(node1.network.myAddress, forcedID = node3.id)
val restoredFlow = node3.getSingleFlow<NoOpFlow>().first val restoredFlow = node3.getSingleFlow<NoOpFlow>().first
assertEquals(false, restoredFlow.flowStarted) // Not started yet as no network activity has been allowed yet assertEquals(false, restoredFlow.flowStarted) // Not started yet as no network activity has been allowed yet
mockNet.runNetwork() // Allow network map messages to flow mockNet.runNetwork() // Allow network map messages to flow
@ -175,7 +175,7 @@ class FlowFrameworkTests {
node3.stop() node3.stop()
// Now it is completed the flow should leave no Checkpoint. // Now it is completed the flow should leave no Checkpoint.
node3 = mockNet.createNode(node1.info.address, forcedID = node3.id) node3 = mockNet.createNode(node1.network.myAddress, forcedID = node3.id)
mockNet.runNetwork() // Allow network map messages to flow mockNet.runNetwork() // Allow network map messages to flow
node3.smm.executor.flush() node3.smm.executor.flush()
assertTrue(node3.smm.findStateMachines(NoOpFlow::class.java).isEmpty()) assertTrue(node3.smm.findStateMachines(NoOpFlow::class.java).isEmpty())
@ -201,7 +201,7 @@ class FlowFrameworkTests {
var sentCount = 0 var sentCount = 0
mockNet.messagingNetwork.sentMessages.toSessionTransfers().filter { it.isPayloadTransfer }.forEach { sentCount++ } mockNet.messagingNetwork.sentMessages.toSessionTransfers().filter { it.isPayloadTransfer }.forEach { sentCount++ }
val node3 = mockNet.createNode(node1.info.address) val node3 = mockNet.createNode(node1.network.myAddress)
val secondFlow = node3.registerFlowFactory(PingPongFlow::class) { PingPongFlow(it, payload2) } val secondFlow = node3.registerFlowFactory(PingPongFlow::class) { PingPongFlow(it, payload2) }
mockNet.runNetwork() mockNet.runNetwork()
@ -218,7 +218,7 @@ class FlowFrameworkTests {
node2.database.transaction { node2.database.transaction {
assertEquals(1, node2.checkpointStorage.checkpoints().size) // confirm checkpoint assertEquals(1, node2.checkpointStorage.checkpoints().size) // confirm checkpoint
} }
val node2b = mockNet.createNode(node1.info.address, node2.id, advertisedServices = *node2.advertisedServices.toTypedArray()) val node2b = mockNet.createNode(node1.network.myAddress, node2.id, advertisedServices = *node2.advertisedServices.toTypedArray())
node2.manuallyCloseDB() node2.manuallyCloseDB()
val (firstAgain, fut1) = node2b.getSingleFlow<PingPongFlow>() val (firstAgain, fut1) = node2b.getSingleFlow<PingPongFlow>()
// Run the network which will also fire up the second flow. First message should get deduped. So message data stays in sync. // Run the network which will also fire up the second flow. First message should get deduped. So message data stays in sync.
@ -245,7 +245,7 @@ class FlowFrameworkTests {
@Test @Test
fun `sending to multiple parties`() { fun `sending to multiple parties`() {
val node3 = mockNet.createNode(node1.info.address) val node3 = mockNet.createNode(node1.network.myAddress)
mockNet.runNetwork() mockNet.runNetwork()
node2.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() } node2.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() }
node3.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() } node3.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() }
@ -277,7 +277,7 @@ class FlowFrameworkTests {
@Test @Test
fun `receiving from multiple parties`() { fun `receiving from multiple parties`() {
val node3 = mockNet.createNode(node1.info.address) val node3 = mockNet.createNode(node1.network.myAddress)
mockNet.runNetwork() mockNet.runNetwork()
val node2Payload = "Test 1" val node2Payload = "Test 1"
val node3Payload = "Test 2" val node3Payload = "Test 2"
@ -457,7 +457,7 @@ class FlowFrameworkTests {
@Test @Test
fun `FlowException propagated in invocation chain`() { fun `FlowException propagated in invocation chain`() {
val node3 = mockNet.createNode(node1.info.address) val node3 = mockNet.createNode(node1.network.myAddress)
mockNet.runNetwork() mockNet.runNetwork()
node3.registerFlowFactory(ReceiveFlow::class) { ExceptionFlow { MyFlowException("Chain") } } node3.registerFlowFactory(ReceiveFlow::class) { ExceptionFlow { MyFlowException("Chain") } }
@ -471,7 +471,7 @@ class FlowFrameworkTests {
@Test @Test
fun `FlowException thrown and there is a 3rd unrelated party flow`() { fun `FlowException thrown and there is a 3rd unrelated party flow`() {
val node3 = mockNet.createNode(node1.info.address) val node3 = mockNet.createNode(node1.network.myAddress)
mockNet.runNetwork() mockNet.runNetwork()
// Node 2 will send its payload and then block waiting for the receive from node 1. Meanwhile node 1 will move // Node 2 will send its payload and then block waiting for the receive from node 1. Meanwhile node 1 will move
@ -675,7 +675,7 @@ class FlowFrameworkTests {
private inline fun <reified P : FlowLogic<*>> MockNode.restartAndGetRestoredFlow(networkMapNode: MockNode? = null): P { private inline fun <reified P : FlowLogic<*>> MockNode.restartAndGetRestoredFlow(networkMapNode: MockNode? = null): P {
disableDBCloseOnStop() // Handover DB to new node copy disableDBCloseOnStop() // Handover DB to new node copy
stop() stop()
val newNode = mockNet.createNode(networkMapNode?.info?.address, id, advertisedServices = *advertisedServices.toTypedArray()) val newNode = mockNet.createNode(networkMapNode?.network?.myAddress, id, advertisedServices = *advertisedServices.toTypedArray())
newNode.acceptableLiveFiberCountOnStop = 1 newNode.acceptableLiveFiberCountOnStop = 1
manuallyCloseDB() manuallyCloseDB()
mockNet.runNetwork() // allow NetworkMapService messages to stabilise and thus start the state machine mockNet.runNetwork() // allow NetworkMapService messages to stabilise and thus start the state machine

View File

@ -35,7 +35,7 @@ class NotaryServiceTests {
notaryNode = mockNet.createNode( notaryNode = mockNet.createNode(
legalName = DUMMY_NOTARY.name, legalName = DUMMY_NOTARY.name,
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type))) advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type)))
clientNode = mockNet.createNode(networkMapAddress = notaryNode.info.address) clientNode = mockNet.createNode(networkMapAddress = notaryNode.network.myAddress)
mockNet.runNetwork() // Clear network map registration messages mockNet.runNetwork() // Clear network map registration messages
} }

View File

@ -33,7 +33,7 @@ class ValidatingNotaryServiceTests {
legalName = DUMMY_NOTARY.name, legalName = DUMMY_NOTARY.name,
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type)) advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type))
) )
clientNode = mockNet.createNode(networkMapAddress = notaryNode.info.address) clientNode = mockNet.createNode(networkMapAddress = notaryNode.network.myAddress)
mockNet.runNetwork() // Clear network map registration messages mockNet.runNetwork() // Clear network map registration messages
} }

View File

@ -213,7 +213,7 @@ class NodeInterestRatesTest {
fun `network tearoff`() { fun `network tearoff`() {
val mockNet = MockNetwork() val mockNet = MockNetwork()
val n1 = mockNet.createNotaryNode() val n1 = mockNet.createNotaryNode()
val n2 = mockNet.createNode(n1.info.address, advertisedServices = ServiceInfo(NodeInterestRates.Oracle.type)) val n2 = mockNet.createNode(n1.network.myAddress, advertisedServices = ServiceInfo(NodeInterestRates.Oracle.type))
n2.registerInitiatedFlow(NodeInterestRates.FixQueryHandler::class.java) n2.registerInitiatedFlow(NodeInterestRates.FixQueryHandler::class.java)
n2.registerInitiatedFlow(NodeInterestRates.FixSignHandler::class.java) n2.registerInitiatedFlow(NodeInterestRates.FixSignHandler::class.java)
n2.database.transaction { n2.database.transaction {

View File

@ -7,7 +7,7 @@ import net.corda.core.flatMap
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.node.CityDatabase import net.corda.core.node.CityDatabase
import net.corda.core.node.PhysicalLocation import net.corda.core.node.WorldMapLocation
import net.corda.core.node.services.ServiceInfo import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.containsType import net.corda.core.node.services.containsType
import net.corda.core.utilities.DUMMY_MAP import net.corda.core.utilities.DUMMY_MAP
@ -57,7 +57,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
entropyRoot: BigInteger) entropyRoot: BigInteger)
: MockNetwork.MockNode(config, mockNet, networkMapAddress, advertisedServices, id, overrideServices, entropyRoot) { : MockNetwork.MockNode(config, mockNet, networkMapAddress, advertisedServices, id, overrideServices, entropyRoot) {
override fun findMyLocation(): PhysicalLocation? { override fun findMyLocation(): WorldMapLocation? {
return configuration.myLegalName.locationOrNull?.let { CityDatabase[it] } return configuration.myLegalName.locationOrNull?.let { CityDatabase[it] }
} }
} }
@ -80,7 +80,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
fun createAll(): List<SimulatedNode> { fun createAll(): List<SimulatedNode> {
return bankLocations.mapIndexed { i, _ -> return bankLocations.mapIndexed { i, _ ->
// Use deterministic seeds so the simulation is stable. Needed so that party owning keys are stable. // Use deterministic seeds so the simulation is stable. Needed so that party owning keys are stable.
mockNet.createNode(networkMap.info.address, start = false, nodeFactory = this, entropyRoot = BigInteger.valueOf(i.toLong())) as SimulatedNode mockNet.createNode(networkMap.network.myAddress, start = false, nodeFactory = this, entropyRoot = BigInteger.valueOf(i.toLong())) as SimulatedNode
} }
} }
} }
@ -158,10 +158,10 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
val networkMap: SimulatedNode val networkMap: SimulatedNode
= mockNet.createNode(null, nodeFactory = NetworkMapNodeFactory, advertisedServices = ServiceInfo(NetworkMapService.type)) as SimulatedNode = mockNet.createNode(null, nodeFactory = NetworkMapNodeFactory, advertisedServices = ServiceInfo(NetworkMapService.type)) as SimulatedNode
val notary: SimulatedNode val notary: SimulatedNode
= mockNet.createNode(networkMap.info.address, nodeFactory = NotaryNodeFactory, advertisedServices = ServiceInfo(SimpleNotaryService.type)) as SimulatedNode = mockNet.createNode(networkMap.network.myAddress, nodeFactory = NotaryNodeFactory, advertisedServices = ServiceInfo(SimpleNotaryService.type)) as SimulatedNode
val regulators: List<SimulatedNode> = listOf(mockNet.createNode(networkMap.info.address, start = false, nodeFactory = RegulatorFactory) as SimulatedNode) val regulators: List<SimulatedNode> = listOf(mockNet.createNode(networkMap.network.myAddress, start = false, nodeFactory = RegulatorFactory) as SimulatedNode)
val ratesOracle: SimulatedNode val ratesOracle: SimulatedNode
= mockNet.createNode(networkMap.info.address, start = false, nodeFactory = RatesOracleFactory, advertisedServices = ServiceInfo(NodeInterestRates.Oracle.type)) as SimulatedNode = mockNet.createNode(networkMap.network.myAddress, start = false, nodeFactory = RatesOracleFactory, advertisedServices = ServiceInfo(NodeInterestRates.Oracle.type)) as SimulatedNode
// All nodes must be in one of these two lists for the purposes of the visualiser tool. // All nodes must be in one of these two lists for the purposes of the visualiser tool.
val serviceProviders: List<SimulatedNode> = listOf(notary, ratesOracle, networkMap) val serviceProviders: List<SimulatedNode> = listOf(notary, ratesOracle, networkMap)

View File

@ -26,13 +26,13 @@ class DriverTests {
private val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2) private val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2)
private fun nodeMustBeUp(handleFuture: ListenableFuture<out NodeHandle>) = handleFuture.getOrThrow().apply { private fun nodeMustBeUp(handleFuture: ListenableFuture<out NodeHandle>) = handleFuture.getOrThrow().apply {
val hostAndPort = ArtemisMessagingComponent.toHostAndPort(nodeInfo.address) val hostAndPort = nodeInfo.addresses.first()
// Check that the port is bound // Check that the port is bound
addressMustBeBound(executorService, hostAndPort, (this as? NodeHandle.OutOfProcess)?.process) addressMustBeBound(executorService, hostAndPort, (this as? NodeHandle.OutOfProcess)?.process)
} }
private fun nodeMustBeDown(handle: NodeHandle) { private fun nodeMustBeDown(handle: NodeHandle) {
val hostAndPort = ArtemisMessagingComponent.toHostAndPort(handle.nodeInfo.address) val hostAndPort = handle.nodeInfo.addresses.first()
// Check that the port is bound // Check that the port is bound
addressMustNotBeBound(executorService, hostAndPort) addressMustNotBeBound(executorService, hostAndPort)
} }

View File

@ -90,6 +90,7 @@ val MOCK_IDENTITIES = listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_NOTAR
val MOCK_IDENTITY_SERVICE: IdentityService get() = InMemoryIdentityService(MOCK_IDENTITIES, emptyMap(), DUMMY_CA.certificate.cert) val MOCK_IDENTITY_SERVICE: IdentityService get() = InMemoryIdentityService(MOCK_IDENTITIES, emptyMap(), DUMMY_CA.certificate.cert)
val MOCK_VERSION_INFO = VersionInfo(1, "Mock release", "Mock revision", "Mock Vendor") val MOCK_VERSION_INFO = VersionInfo(1, "Mock release", "Mock revision", "Mock Vendor")
val MOCK_HOST_AND_PORT = HostAndPort.fromParts("mockHost", 30000)
fun generateStateRef() = StateRef(SecureHash.randomSHA256(), 0) fun generateStateRef() = StateRef(SecureHash.randomSHA256(), 0)

View File

@ -82,6 +82,8 @@ class InMemoryMessagingNetwork(
// Holds the mapping from services to peers advertising the service. // Holds the mapping from services to peers advertising the service.
private val serviceToPeersMapping = HashMap<ServiceHandle, LinkedHashSet<PeerHandle>>() private val serviceToPeersMapping = HashMap<ServiceHandle, LinkedHashSet<PeerHandle>>()
// Holds the mapping from node's X500Name to PeerHandle.
private val peersMapping = HashMap<X500Name, PeerHandle>()
@Suppress("unused") // Used by the visualiser tool. @Suppress("unused") // Used by the visualiser tool.
/** A stream of (sender, message, recipients) triples */ /** A stream of (sender, message, recipients) triples */
@ -127,10 +129,12 @@ class InMemoryMessagingNetwork(
id: Int, id: Int,
executor: AffinityExecutor, executor: AffinityExecutor,
advertisedServices: List<ServiceEntry>, advertisedServices: List<ServiceEntry>,
description: X500Name? = null, description: X500Name = X509Utilities.getX509Name("In memory node $id","London","demo@r3.com",null),
database: Database) database: Database)
: MessagingServiceBuilder<InMemoryMessaging> { : MessagingServiceBuilder<InMemoryMessaging> {
return Builder(manuallyPumped, PeerHandle(id, description ?: X509Utilities.getX509Name("In memory node $id","London","demo@r3.com",null)), advertisedServices.map(::ServiceHandle), executor, database = database) val peerHandle = PeerHandle(id, description)
peersMapping[peerHandle.description] = peerHandle // Assume that the same name - the same entity in MockNetwork.
return Builder(manuallyPumped, peerHandle, advertisedServices.map(::ServiceHandle), executor, database = database)
} }
interface LatencyCalculator { interface LatencyCalculator {
@ -330,7 +334,7 @@ class InMemoryMessagingNetwork(
override fun getAddressOfParty(partyInfo: PartyInfo): MessageRecipients { override fun getAddressOfParty(partyInfo: PartyInfo): MessageRecipients {
return when (partyInfo) { return when (partyInfo) {
is PartyInfo.Node -> partyInfo.node.address is PartyInfo.Node -> peersMapping[partyInfo.party.name] ?: throw IllegalArgumentException("No MockNode for party ${partyInfo.party.name}")
is PartyInfo.Service -> ServiceHandle(partyInfo.service) is PartyInfo.Service -> ServiceHandle(partyInfo.service)
} }
} }

View File

@ -1,9 +1,9 @@
package net.corda.testing.node package net.corda.testing.node
import co.paralleluniverse.common.util.VisibleForTesting import co.paralleluniverse.common.util.VisibleForTesting
import com.google.common.net.HostAndPort
import net.corda.core.crypto.entropyToKeyPair import net.corda.core.crypto.entropyToKeyPair
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.node.services.NetworkMapCache import net.corda.core.node.services.NetworkMapCache
import net.corda.core.utilities.getTestPartyAndCertificate import net.corda.core.utilities.getTestPartyAndCertificate
@ -21,15 +21,15 @@ class MockNetworkMapCache : InMemoryNetworkMapCache() {
private companion object { private companion object {
val BANK_C = getTestPartyAndCertificate(getTestX509Name("Bank C"), entropyToKeyPair(BigInteger.valueOf(1000)).public) val BANK_C = getTestPartyAndCertificate(getTestX509Name("Bank C"), entropyToKeyPair(BigInteger.valueOf(1000)).public)
val BANK_D = getTestPartyAndCertificate(getTestX509Name("Bank D"), entropyToKeyPair(BigInteger.valueOf(2000)).public) val BANK_D = getTestPartyAndCertificate(getTestX509Name("Bank D"), entropyToKeyPair(BigInteger.valueOf(2000)).public)
val BANK_C_ADDR: HostAndPort = HostAndPort.fromParts("bankC", 8080)
val BANK_D_ADDR: HostAndPort = HostAndPort.fromParts("bankD", 8080)
} }
override val changed: Observable<NetworkMapCache.MapChange> = PublishSubject.create<NetworkMapCache.MapChange>() override val changed: Observable<NetworkMapCache.MapChange> = PublishSubject.create<NetworkMapCache.MapChange>()
data class MockAddress(val id: String) : SingleMessageRecipient
init { init {
val mockNodeA = NodeInfo(MockAddress("bankC:8080"), BANK_C, MOCK_VERSION_INFO.platformVersion) val mockNodeA = NodeInfo(listOf(BANK_C_ADDR), BANK_C, setOf(BANK_C), MOCK_VERSION_INFO.platformVersion)
val mockNodeB = NodeInfo(MockAddress("bankD:8080"), BANK_D, MOCK_VERSION_INFO.platformVersion) val mockNodeB = NodeInfo(listOf(BANK_D_ADDR), BANK_D, setOf(BANK_D), MOCK_VERSION_INFO.platformVersion)
registeredNodes[mockNodeA.legalIdentity.owningKey] = mockNodeA registeredNodes[mockNodeA.legalIdentity.owningKey] = mockNodeA
registeredNodes[mockNodeB.legalIdentity.owningKey] = mockNodeB registeredNodes[mockNodeB.legalIdentity.owningKey] = mockNodeB
runWithoutMapService() runWithoutMapService()

View File

@ -2,6 +2,7 @@ package net.corda.testing.node
import com.google.common.jimfs.Configuration.unix import com.google.common.jimfs.Configuration.unix
import com.google.common.jimfs.Jimfs import com.google.common.jimfs.Jimfs
import com.google.common.net.HostAndPort
import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import com.nhaarman.mockito_kotlin.whenever import com.nhaarman.mockito_kotlin.whenever
@ -14,7 +15,7 @@ import net.corda.core.messaging.MessageRecipients
import net.corda.core.messaging.RPCOps import net.corda.core.messaging.RPCOps
import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.node.CordaPluginRegistry import net.corda.core.node.CordaPluginRegistry
import net.corda.core.node.PhysicalLocation import net.corda.core.node.WorldMapLocation
import net.corda.core.node.ServiceEntry import net.corda.core.node.ServiceEntry
import net.corda.core.node.services.* import net.corda.core.node.services.*
import net.corda.core.utilities.DUMMY_NOTARY_KEY import net.corda.core.utilities.DUMMY_NOTARY_KEY
@ -222,12 +223,14 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
override fun noNetworkMapConfigured(): ListenableFuture<Unit> = Futures.immediateFuture(Unit) override fun noNetworkMapConfigured(): ListenableFuture<Unit> = Futures.immediateFuture(Unit)
// There is no need to slow down the unit tests by initialising CityDatabase // There is no need to slow down the unit tests by initialising CityDatabase
override fun findMyLocation(): PhysicalLocation? = null override fun findMyLocation(): WorldMapLocation? = null
override fun makeUniquenessProvider(type: ServiceType): UniquenessProvider = InMemoryUniquenessProvider() override fun makeUniquenessProvider(type: ServiceType): UniquenessProvider = InMemoryUniquenessProvider()
override fun makeTransactionVerifierService() = InMemoryTransactionVerifierService(1) override fun makeTransactionVerifierService() = InMemoryTransactionVerifierService(1)
override fun myAddresses(): List<HostAndPort> = listOf(HostAndPort.fromHost("mockHost"))
override fun start(): MockNode { override fun start(): MockNode {
super.start() super.start()
mockNet.identities.add(info.legalIdentityAndCert) mockNet.identities.add(info.legalIdentityAndCert)
@ -242,7 +245,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
// This does not indirect through the NodeInfo object so it can be called before the node is started. // This does not indirect through the NodeInfo object so it can be called before the node is started.
// It is used from the network visualiser tool. // It is used from the network visualiser tool.
@Suppress("unused") val place: PhysicalLocation get() = findMyLocation()!! @Suppress("unused") val place: WorldMapLocation get() = findMyLocation()!!
fun pumpReceive(block: Boolean = false): InMemoryMessagingNetwork.MessageTransfer? { fun pumpReceive(block: Boolean = false): InMemoryMessagingNetwork.MessageTransfer? {
return (network as InMemoryMessagingNetwork.InMemoryMessaging).pumpReceive(block) return (network as InMemoryMessagingNetwork.InMemoryMessaging).pumpReceive(block)
@ -351,7 +354,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
null null
return Pair( return Pair(
createNode(null, -1, nodeFactory, true, firstNodeName, notaryOverride, BigInteger.valueOf(random63BitValue()), ServiceInfo(NetworkMapService.type), notaryServiceInfo), createNode(null, -1, nodeFactory, true, firstNodeName, notaryOverride, BigInteger.valueOf(random63BitValue()), ServiceInfo(NetworkMapService.type), notaryServiceInfo),
createNode(nodes[0].info.address, -1, nodeFactory, true, secondNodeName) createNode(nodes[0].network.myAddress, -1, nodeFactory, true, secondNodeName)
) )
} }
@ -374,11 +377,12 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
else else
null null
val mapNode = createNode(null, nodeFactory = nodeFactory, advertisedServices = ServiceInfo(NetworkMapService.type)) val mapNode = createNode(null, nodeFactory = nodeFactory, advertisedServices = ServiceInfo(NetworkMapService.type))
val notaryNode = createNode(mapNode.info.address, nodeFactory = nodeFactory, overrideServices = notaryOverride, val mapAddress = mapNode.network.myAddress
val notaryNode = createNode(mapAddress, nodeFactory = nodeFactory, overrideServices = notaryOverride,
advertisedServices = notaryServiceInfo) advertisedServices = notaryServiceInfo)
val nodes = ArrayList<MockNode>() val nodes = ArrayList<MockNode>()
repeat(numPartyNodes) { repeat(numPartyNodes) {
nodes += createPartyNode(mapNode.info.address) nodes += createPartyNode(mapAddress)
} }
nodes.forEach { itNode -> nodes.forEach { itNode ->
nodes.map { it.info.legalIdentityAndCert }.forEach(itNode.services.identityService::registerIdentity) nodes.map { it.info.legalIdentityAndCert }.forEach(itNode.services.identityService::registerIdentity)

View File

@ -1,5 +1,6 @@
package net.corda.testing.node package net.corda.testing.node
import com.google.common.net.HostAndPort
import net.corda.core.contracts.Attachment import net.corda.core.contracts.Attachment
import net.corda.core.crypto.* import net.corda.core.crypto.*
import net.corda.core.flows.StateMachineRunId import net.corda.core.flows.StateMachineRunId
@ -73,7 +74,10 @@ open class MockServices(vararg val keys: KeyPair) : ServiceHub {
override val vaultQueryService: VaultQueryService get() = throw UnsupportedOperationException() override val vaultQueryService: VaultQueryService get() = throw UnsupportedOperationException()
override val networkMapCache: NetworkMapCache get() = throw UnsupportedOperationException() override val networkMapCache: NetworkMapCache get() = throw UnsupportedOperationException()
override val clock: Clock get() = Clock.systemUTC() override val clock: Clock get() = Clock.systemUTC()
override val myInfo: NodeInfo get() = NodeInfo(object : SingleMessageRecipient {}, getTestPartyAndCertificate(MEGA_CORP.name, key.public), MOCK_VERSION_INFO.platformVersion) override val myInfo: NodeInfo get() {
val identity = getTestPartyAndCertificate(MEGA_CORP.name, key.public)
return NodeInfo(listOf(HostAndPort.fromHost("localhost")), identity, setOf(identity), MOCK_VERSION_INFO.platformVersion)
}
override val transactionVerifierService: TransactionVerifierService get() = InMemoryTransactionVerifierService(2) override val transactionVerifierService: TransactionVerifierService get() = InMemoryTransactionVerifierService(2)
fun makeVaultService(dataSourceProps: Properties, hibernateConfig: HibernateConfiguration = HibernateConfiguration(NodeSchemaService())): VaultService { fun makeVaultService(dataSourceProps: Properties, hibernateConfig: HibernateConfiguration = HibernateConfiguration(NodeSchemaService())): VaultService {

View File

@ -18,7 +18,7 @@ import net.corda.core.crypto.commonName
import net.corda.core.div import net.corda.core.div
import net.corda.core.exists import net.corda.core.exists
import net.corda.core.node.CityDatabase import net.corda.core.node.CityDatabase
import net.corda.core.node.PhysicalLocation import net.corda.core.node.WorldMapLocation
import net.corda.core.readAllLines import net.corda.core.readAllLines
import net.corda.core.utilities.normaliseLegalName import net.corda.core.utilities.normaliseLegalName
import net.corda.core.utilities.validateLegalName import net.corda.core.utilities.validateLegalName
@ -211,7 +211,7 @@ class NodeTabView : Fragment() {
CityDatabase.cityMap.values.map { it.countryCode }.toSet().map { it to Image(resources["/net/corda/demobench/flags/$it.png"]) }.toMap() CityDatabase.cityMap.values.map { it.countryCode }.toSet().map { it to Image(resources["/net/corda/demobench/flags/$it.png"]) }.toMap()
} }
private fun Pane.nearestCityField(): ComboBox<PhysicalLocation> { private fun Pane.nearestCityField(): ComboBox<WorldMapLocation> {
return combobox(model.nearestCity, CityDatabase.cityMap.values.toList().sortedBy { it.description }) { return combobox(model.nearestCity, CityDatabase.cityMap.values.toList().sortedBy { it.description }) {
minWidth = textWidth minWidth = textWidth
styleClass += "city-picker" styleClass += "city-picker"
@ -229,9 +229,9 @@ class NodeTabView : Fragment() {
if (it == null) error("Please select a city") else null if (it == null) error("Please select a city") else null
} }
converter = object : StringConverter<PhysicalLocation>() { converter = object : StringConverter<WorldMapLocation>() {
override fun toString(loc: PhysicalLocation?) = loc?.description ?: "" override fun toString(loc: WorldMapLocation?) = loc?.description ?: ""
override fun fromString(string: String): PhysicalLocation? = CityDatabase[string] override fun fromString(string: String): WorldMapLocation? = CityDatabase[string]
} }
value = CityDatabase["London"] value = CityDatabase["London"]

View File

@ -98,7 +98,7 @@ class Network : CordaView() {
copyableLabel(SimpleObjectProperty(node.legalIdentity.owningKey.toBase58String())).apply { minWidth = 400.0 } copyableLabel(SimpleObjectProperty(node.legalIdentity.owningKey.toBase58String())).apply { minWidth = 400.0 }
} }
row("Services :") { label(node.advertisedServices.map { it.info }.joinToString(", ")) } row("Services :") { label(node.advertisedServices.map { it.info }.joinToString(", ")) }
node.physicalLocation?.apply { row("Location :") { label(this@apply.description) } } node.worldMapLocation?.apply { row("Location :") { label(this@apply.description) } }
} }
} }
setOnMouseClicked { setOnMouseClicked {
@ -122,7 +122,7 @@ class Network : CordaView() {
contentDisplay = ContentDisplay.TOP contentDisplay = ContentDisplay.TOP
val coordinate = Bindings.createObjectBinding({ val coordinate = Bindings.createObjectBinding({
// These coordinates are obtained when we generate the map using TileMill. // These coordinates are obtained when we generate the map using TileMill.
node.physicalLocation?.coordinate?.project(mapPane.width, mapPane.height, 85.0511, -85.0511, -180.0, 180.0) ?: Pair(0.0, 0.0) node.worldMapLocation?.coordinate?.project(mapPane.width, mapPane.height, 85.0511, -85.0511, -180.0, 180.0) ?: Pair(0.0, 0.0)
}, arrayOf(mapPane.widthProperty(), mapPane.heightProperty())) }, arrayOf(mapPane.widthProperty(), mapPane.heightProperty()))
// Center point of the label. // Center point of the label.
layoutXProperty().bind(coordinate.map { it.first - width / 2 }) layoutXProperty().bind(coordinate.map { it.first - width / 2 })

View File

@ -24,7 +24,6 @@ import net.corda.contracts.asset.Cash
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.* import net.corda.core.crypto.*
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.explorer.AmountDiff import net.corda.explorer.AmountDiff
import net.corda.explorer.formatters.AmountFormatter import net.corda.explorer.formatters.AmountFormatter

View File

@ -22,7 +22,6 @@ import net.corda.core.contracts.sumOrNull
import net.corda.core.contracts.withoutIssuer import net.corda.core.contracts.withoutIssuer
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.crypto.commonName
import net.corda.core.flows.FlowException import net.corda.core.flows.FlowException
import net.corda.core.getOrThrow import net.corda.core.getOrThrow
import net.corda.core.messaging.startFlow import net.corda.core.messaging.startFlow