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
import com.google.common.net.HostAndPort
import net.corda.core.identity.Party
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.ServiceType
import net.corda.core.serialization.CordaSerializable
import org.bouncycastle.cert.X509CertificateHolder
/**
* 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.
*/
// TODO We currently don't support multi-IP/multi-identity nodes, we only left slots in the data structures.
@CordaSerializable
data class NodeInfo(val address: SingleMessageRecipient,
val legalIdentityAndCert: PartyAndCertificate,
data class NodeInfo(val addresses: List<HostAndPort>,
val legalIdentityAndCert: PartyAndCertificate, //TODO This field will be removed in future PR which gets rid of services.
val legalIdentitiesAndCerts: Set<PartyAndCertificate>,
val platformVersion: Int,
var advertisedServices: List<ServiceEntry> = emptyList(),
val physicalLocation: PhysicalLocation? = null) {
val worldMapLocation: WorldMapLocation? = null) {
init {
require(advertisedServices.none { it.identity == legalIdentityAndCert }) { "Service identities must be different from node legal identity" }
}
val legalIdentity: Party
get() = legalIdentityAndCert.party
val notaryIdentity: Party
@ -35,7 +35,4 @@ data class NodeInfo(val address: SingleMessageRecipient,
fun serviceIdentities(type: ServiceType): List<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.
*/
@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.
*/
object CityDatabase {
private val matcher = Regex("^([a-zA-Z- ]*) \\((..)\\)$")
private val caseInsensitiveLookups = HashMap<String, PhysicalLocation>()
val cityMap = HashMap<String, PhysicalLocation>()
private val caseInsensitiveLookups = HashMap<String, WorldMapLocation>()
val cityMap = HashMap<String, WorldMapLocation>()
init {
javaClass.getResourceAsStream("cities.txt").bufferedReader().useLines { lines ->
@ -60,7 +60,7 @@ object CityDatabase {
val (name, lng, lat) = line.split('\t')
val matchResult = matcher.matchEntire(name) ?: throw Exception("Could not parse line: $line")
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
cityMap[city] = location
}

View File

@ -69,7 +69,7 @@ class AttachmentSerializationTest {
fun setUp() {
mockNet = MockNetwork()
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.
mockNet.runNetwork()
}
@ -149,7 +149,7 @@ class AttachmentSerializationTest {
private fun rebootClientAndGetAttachmentContent(checkAttachmentsOnLoad: Boolean = true): String {
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 {
return object : MockNetwork.MockNode(config, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) {
override fun startMessagingService(rpcOps: RPCOps) {

View File

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

View File

@ -6,6 +6,12 @@ from the previous milestone release.
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
----------

View File

@ -12,8 +12,6 @@ import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.InitiatingFlow
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.services.unconsumedStates
import net.corda.core.serialization.CordaSerializable

View File

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

View File

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

View File

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

View File

@ -6,6 +6,8 @@ import net.corda.core.crypto.toBase58String
import net.corda.core.messaging.MessageRecipientGroup
import net.corda.core.messaging.MessageRecipients
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.serialization.CordaSerializable
import net.corda.core.serialization.SingletonSerializeAsToken
@ -34,18 +36,6 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
const val P2P_QUEUE = "p2p.inbound"
const val NOTIFICATIONS_ADDRESS = "${INTERNAL_PREFIX}activemq.notifications"
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 {
@ -57,7 +47,7 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
}
@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
}
@ -116,4 +106,12 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
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) }
replicaIds.forEach { replicaId ->
mockNet.createNode(
node.info.address,
node.network.myAddress,
advertisedServices = bftNotaryService,
configOverrides = {
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.NodeRegistration
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.node.NodeBasedTest
import net.corda.testing.node.SimpleNode
@ -69,7 +70,7 @@ class P2PSecurityTest : NodeBasedTest() {
private fun SimpleNode.registerWithNetworkMap(registrationName: X500Name): ListenableFuture<NetworkMapService.RegistrationResponse> {
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 request = RegistrationRequest(registration.toWire(keyService, identity.public), 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.google.common.annotations.VisibleForTesting
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.MoreExecutors
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.configureDatabase
import net.corda.node.utilities.transaction
import net.corda.nodeapi.ArtemisMessagingComponent
import org.apache.activemq.artemis.utils.ReusableLatch
import org.bouncycastle.asn1.x500.X500Name
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] }
}
@ -548,7 +550,9 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
private fun makeInfo(): NodeInfo {
val advertisedServiceEntries = makeServiceEntries()
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 }) {
"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.
return sendNetworkMapRegistration(address).flatMap { (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 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 */
protected open fun noNetworkMapConfigured(): ListenableFuture<Unit> {
// 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.utilities.AddressUtils
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.PEER_USER
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:
* jdbc:h2:tcp://<host>:<port>/node

View File

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

View File

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

View File

@ -564,11 +564,10 @@ class NodeMessagingClient(override val config: NodeConfiguration,
}
}
override fun getAddressOfParty(partyInfo: PartyInfo): MessageRecipients {
return when (partyInfo) {
is PartyInfo.Node -> partyInfo.node.address
is PartyInfo.Service -> ArtemisMessagingComponent.ServiceAddress(partyInfo.service.identity.owningKey)
is PartyInfo.Node -> getArtemisPeerAddress(partyInfo.node)
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> {
// Fetch the network map and register for updates at the same time
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()
}
_registrationFuture.setFuture(future)

View File

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

View File

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

View File

@ -114,7 +114,7 @@ class AttachmentTests {
}
}
}, 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()
// Insert an attachment into node zero's store directly.

View File

@ -34,15 +34,15 @@ class InMemoryMessagingTests {
@Test
fun basics() {
val node1 = mockNet.createNode(advertisedServices = ServiceInfo(NetworkMapService.type))
val node2 = mockNet.createNode(networkMapAddress = node1.info.address)
val node3 = mockNet.createNode(networkMapAddress = node1.info.address)
val node2 = mockNet.createNode(networkMapAddress = node1.network.myAddress)
val node3 = mockNet.createNode(networkMapAddress = node1.network.myAddress)
val bits = "test-content".toByteArray()
var finalDelivery: Message? = null
with(node2) {
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
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)
@ -63,8 +63,8 @@ class InMemoryMessagingTests {
@Test
fun broadcast() {
val node1 = mockNet.createNode(advertisedServices = ServiceInfo(NetworkMapService.type))
val node2 = mockNet.createNode(networkMapAddress = node1.info.address)
val node3 = mockNet.createNode(networkMapAddress = node1.info.address)
val node2 = mockNet.createNode(networkMapAddress = node1.network.myAddress)
val node3 = mockNet.createNode(networkMapAddress = node1.network.myAddress)
val bits = "test-content".toByteArray()
@ -82,7 +82,7 @@ class InMemoryMessagingTests {
@Test
fun `skip unhandled messages`() {
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
node1.network.addMessageHandler("valid_message") { _, _ ->

View File

@ -127,8 +127,8 @@ class TwoPartyTradeFlowTests {
ledger {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = mockNet.createPartyNode(notaryNode.info.address, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.info.address, BOB.name)
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
aliceNode.disableDBCloseOnStop()
bobNode.disableDBCloseOnStop()
@ -173,13 +173,13 @@ class TwoPartyTradeFlowTests {
fun `shutdown and restore`() {
ledger {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = mockNet.createPartyNode(notaryNode.info.address, ALICE.name)
var bobNode = mockNet.createPartyNode(notaryNode.info.address, BOB.name)
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
var bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
aliceNode.disableDBCloseOnStop()
bobNode.disableDBCloseOnStop()
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
@ -291,8 +291,8 @@ class TwoPartyTradeFlowTests {
@Test
fun `check dependencies of sale asset are resolved`() {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = makeNodeWithTracking(notaryNode.info.address, ALICE.name)
val bobNode = makeNodeWithTracking(notaryNode.info.address, BOB.name)
val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
ledger(aliceNode.services) {
@ -390,8 +390,8 @@ class TwoPartyTradeFlowTests {
@Test
fun `track works`() {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = makeNodeWithTracking(notaryNode.info.address, ALICE.name)
val bobNode = makeNodeWithTracking(notaryNode.info.address, BOB.name)
val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
ledger(aliceNode.services) {
@ -528,8 +528,8 @@ class TwoPartyTradeFlowTests {
expectedMessageSubstring: String
) {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = mockNet.createPartyNode(notaryNode.info.address, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.info.address, BOB.name)
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val issuer = MEGA_CORP.ref(1, 2, 3)
val bobsBadCash = bobNode.database.transaction {

View File

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

View File

@ -94,8 +94,8 @@ class ScheduledFlowTests {
notaryNode = mockNet.createNode(
legalName = DUMMY_NOTARY.name,
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type)))
nodeA = mockNet.createNode(notaryNode.info.address, start = false)
nodeB = mockNet.createNode(notaryNode.info.address, start = false)
nodeA = mockNet.createNode(notaryNode.network.myAddress, start = false)
nodeB = mockNet.createNode(notaryNode.network.myAddress, start = false)
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> {
val request = FetchMapRequest(subscribe, ifChangedSinceVersion, info.address)
val response = services.networkService.sendRequest<FetchMapResponse>(FETCH_TOPIC, request, mapServiceNode.info.address)
val request = FetchMapRequest(subscribe, ifChangedSinceVersion, network.myAddress)
val response = services.networkService.sendRequest<FetchMapResponse>(FETCH_TOPIC, request, mapServiceNode.network.myAddress)
mockNet.runNetwork()
return response.getOrThrow().nodes?.map { it.toChanged() } ?: emptyList()
}
@ -198,8 +198,8 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
}
private fun MockNode.identityQuery(): NodeInfo? {
val request = QueryIdentityRequest(info.legalIdentityAndCert, info.address)
val response = services.networkService.sendRequest<QueryIdentityResponse>(QUERY_TOPIC, request, mapServiceNode.info.address)
val request = QueryIdentityRequest(info.legalIdentityAndCert, network.myAddress)
val response = services.networkService.sendRequest<QueryIdentityResponse>(QUERY_TOPIC, request, mapServiceNode.network.myAddress)
mockNet.runNetwork()
return response.getOrThrow().node
}
@ -216,39 +216,39 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
}
val expires = Instant.now() + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
val nodeRegistration = NodeRegistration(info, distinctSerial, addOrRemove, expires)
val request = RegistrationRequest(nodeRegistration.toWire(services.keyManagementService, services.legalIdentityKey), info.address)
val response = services.networkService.sendRequest<RegistrationResponse>(REGISTER_TOPIC, request, mapServiceNode.info.address)
val request = RegistrationRequest(nodeRegistration.toWire(services.keyManagementService, services.legalIdentityKey), network.myAddress)
val response = services.networkService.sendRequest<RegistrationResponse>(REGISTER_TOPIC, request, mapServiceNode.network.myAddress)
mockNet.runNetwork()
return response
}
private fun MockNode.subscribe(): List<Update> {
val request = SubscribeRequest(true, info.address)
val request = SubscribeRequest(true, network.myAddress)
val updates = BlockingArrayQueue<Update>()
services.networkService.addMessageHandler(PUSH_TOPIC, DEFAULT_SESSION_ID) { message, _ ->
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()
assertThat(response.getOrThrow().confirmed).isTrue()
return updates
}
private fun MockNode.unsubscribe() {
val request = SubscribeRequest(false, info.address)
val response = services.networkService.sendRequest<SubscribeResponse>(SUBSCRIPTION_TOPIC, request, mapServiceNode.info.address)
val request = SubscribeRequest(false, network.myAddress)
val response = services.networkService.sendRequest<SubscribeResponse>(SUBSCRIPTION_TOPIC, request, mapServiceNode.network.myAddress)
mockNet.runNetwork()
assertThat(response.getOrThrow().confirmed).isTrue()
}
private fun MockNode.ackUpdate(mapVersion: Int) {
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()
}
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()
lastSerial = System.currentTimeMillis()
return node

View File

@ -16,7 +16,7 @@ class InMemoryNetworkMapCacheTest {
@Test
fun registerWithNetwork() {
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()
future.getOrThrow()
}

View File

@ -81,8 +81,8 @@ class FlowFrameworkTests {
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
// service addressing.
notary1 = mockNet.createNotaryNode(networkMapAddr = node1.services.myInfo.address, overrideServices = overrideServices, serviceName = notaryService.name)
notary2 = 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.network.myAddress, overrideServices = overrideServices, serviceName = notaryService.name)
mockNet.messagingNetwork.receivedMessages.toSessionTransfers().forEach { sessionTransfers += it }
mockNet.runNetwork()
@ -148,7 +148,7 @@ class FlowFrameworkTests {
@Test
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()
node3.services.startFlow(flow)
assertEquals(false, flow.flowStarted) // Not started yet as no network activity has been allowed yet
@ -158,14 +158,14 @@ class FlowFrameworkTests {
@Test
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()
node3.services.startFlow(flow)
assertEquals(false, flow.flowStarted) // Not started yet as no network activity has been allowed yet
node3.disableDBCloseOnStop()
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
assertEquals(false, restoredFlow.flowStarted) // Not started yet as no network activity has been allowed yet
mockNet.runNetwork() // Allow network map messages to flow
@ -175,7 +175,7 @@ class FlowFrameworkTests {
node3.stop()
// 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
node3.smm.executor.flush()
assertTrue(node3.smm.findStateMachines(NoOpFlow::class.java).isEmpty())
@ -201,7 +201,7 @@ class FlowFrameworkTests {
var sentCount = 0
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) }
mockNet.runNetwork()
@ -218,7 +218,7 @@ class FlowFrameworkTests {
node2.database.transaction {
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()
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.
@ -245,7 +245,7 @@ class FlowFrameworkTests {
@Test
fun `sending to multiple parties`() {
val node3 = mockNet.createNode(node1.info.address)
val node3 = mockNet.createNode(node1.network.myAddress)
mockNet.runNetwork()
node2.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() }
node3.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() }
@ -277,7 +277,7 @@ class FlowFrameworkTests {
@Test
fun `receiving from multiple parties`() {
val node3 = mockNet.createNode(node1.info.address)
val node3 = mockNet.createNode(node1.network.myAddress)
mockNet.runNetwork()
val node2Payload = "Test 1"
val node3Payload = "Test 2"
@ -457,7 +457,7 @@ class FlowFrameworkTests {
@Test
fun `FlowException propagated in invocation chain`() {
val node3 = mockNet.createNode(node1.info.address)
val node3 = mockNet.createNode(node1.network.myAddress)
mockNet.runNetwork()
node3.registerFlowFactory(ReceiveFlow::class) { ExceptionFlow { MyFlowException("Chain") } }
@ -471,7 +471,7 @@ class FlowFrameworkTests {
@Test
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()
// 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 {
disableDBCloseOnStop() // Handover DB to new node copy
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
manuallyCloseDB()
mockNet.runNetwork() // allow NetworkMapService messages to stabilise and thus start the state machine

View File

@ -35,7 +35,7 @@ class NotaryServiceTests {
notaryNode = mockNet.createNode(
legalName = DUMMY_NOTARY.name,
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
}

View File

@ -33,7 +33,7 @@ class ValidatingNotaryServiceTests {
legalName = DUMMY_NOTARY.name,
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
}

View File

@ -213,7 +213,7 @@ class NodeInterestRatesTest {
fun `network tearoff`() {
val mockNet = MockNetwork()
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.FixSignHandler::class.java)
n2.database.transaction {

View File

@ -64,4 +64,4 @@ object UpdateBusinessDayFlow {
send(recipient.legalIdentity, UpdateBusinessDayMessage(date))
}
}
}
}

View File

@ -7,7 +7,7 @@ import net.corda.core.flatMap
import net.corda.core.flows.FlowLogic
import net.corda.core.messaging.SingleMessageRecipient
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.containsType
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>?,
entropyRoot: BigInteger)
: MockNetwork.MockNode(config, mockNet, networkMapAddress, advertisedServices, id, overrideServices, entropyRoot) {
override fun findMyLocation(): PhysicalLocation? {
override fun findMyLocation(): WorldMapLocation? {
return configuration.myLegalName.locationOrNull?.let { CityDatabase[it] }
}
}
@ -80,7 +80,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
fun createAll(): List<SimulatedNode> {
return bankLocations.mapIndexed { i, _ ->
// 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
= mockNet.createNode(null, nodeFactory = NetworkMapNodeFactory, advertisedServices = ServiceInfo(NetworkMapService.type)) as SimulatedNode
val notary: SimulatedNode
= mockNet.createNode(networkMap.info.address, nodeFactory = NotaryNodeFactory, advertisedServices = ServiceInfo(SimpleNotaryService.type)) as SimulatedNode
val regulators: List<SimulatedNode> = listOf(mockNet.createNode(networkMap.info.address, start = false, nodeFactory = RegulatorFactory) as SimulatedNode)
= mockNet.createNode(networkMap.network.myAddress, nodeFactory = NotaryNodeFactory, advertisedServices = ServiceInfo(SimpleNotaryService.type)) as SimulatedNode
val regulators: List<SimulatedNode> = listOf(mockNet.createNode(networkMap.network.myAddress, start = false, nodeFactory = RegulatorFactory) as 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.
val serviceProviders: List<SimulatedNode> = listOf(notary, ratesOracle, networkMap)

View File

@ -26,13 +26,13 @@ class DriverTests {
private val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2)
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
addressMustBeBound(executorService, hostAndPort, (this as? NodeHandle.OutOfProcess)?.process)
}
private fun nodeMustBeDown(handle: NodeHandle) {
val hostAndPort = ArtemisMessagingComponent.toHostAndPort(handle.nodeInfo.address)
val hostAndPort = handle.nodeInfo.addresses.first()
// Check that the port is bound
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_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)

View File

@ -82,6 +82,8 @@ class InMemoryMessagingNetwork(
// Holds the mapping from services to peers advertising the service.
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.
/** A stream of (sender, message, recipients) triples */
@ -127,10 +129,12 @@ class InMemoryMessagingNetwork(
id: Int,
executor: AffinityExecutor,
advertisedServices: List<ServiceEntry>,
description: X500Name? = null,
description: X500Name = X509Utilities.getX509Name("In memory node $id","London","demo@r3.com",null),
database: Database)
: 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 {
@ -330,7 +334,7 @@ class InMemoryMessagingNetwork(
override fun getAddressOfParty(partyInfo: PartyInfo): MessageRecipients {
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)
}
}

View File

@ -1,9 +1,9 @@
package net.corda.testing.node
import co.paralleluniverse.common.util.VisibleForTesting
import com.google.common.net.HostAndPort
import net.corda.core.crypto.entropyToKeyPair
import net.corda.core.identity.Party
import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.node.NodeInfo
import net.corda.core.node.services.NetworkMapCache
import net.corda.core.utilities.getTestPartyAndCertificate
@ -21,15 +21,15 @@ class MockNetworkMapCache : InMemoryNetworkMapCache() {
private companion object {
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_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>()
data class MockAddress(val id: String) : SingleMessageRecipient
init {
val mockNodeA = NodeInfo(MockAddress("bankC:8080"), BANK_C, MOCK_VERSION_INFO.platformVersion)
val mockNodeB = NodeInfo(MockAddress("bankD:8080"), BANK_D, MOCK_VERSION_INFO.platformVersion)
val mockNodeA = NodeInfo(listOf(BANK_C_ADDR), BANK_C, setOf(BANK_C), 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[mockNodeB.legalIdentity.owningKey] = mockNodeB
runWithoutMapService()

View File

@ -2,6 +2,7 @@ package net.corda.testing.node
import com.google.common.jimfs.Configuration.unix
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.ListenableFuture
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.SingleMessageRecipient
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.services.*
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)
// 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 makeTransactionVerifierService() = InMemoryTransactionVerifierService(1)
override fun myAddresses(): List<HostAndPort> = listOf(HostAndPort.fromHost("mockHost"))
override fun start(): MockNode {
super.start()
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.
// 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? {
return (network as InMemoryMessagingNetwork.InMemoryMessaging).pumpReceive(block)
@ -351,7 +354,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
null
return Pair(
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
null
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)
val nodes = ArrayList<MockNode>()
repeat(numPartyNodes) {
nodes += createPartyNode(mapNode.info.address)
nodes += createPartyNode(mapAddress)
}
nodes.forEach { itNode ->
nodes.map { it.info.legalIdentityAndCert }.forEach(itNode.services.identityService::registerIdentity)

View File

@ -1,5 +1,6 @@
package net.corda.testing.node
import com.google.common.net.HostAndPort
import net.corda.core.contracts.Attachment
import net.corda.core.crypto.*
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 networkMapCache: NetworkMapCache get() = throw UnsupportedOperationException()
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)
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.exists
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.utilities.normaliseLegalName
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()
}
private fun Pane.nearestCityField(): ComboBox<PhysicalLocation> {
private fun Pane.nearestCityField(): ComboBox<WorldMapLocation> {
return combobox(model.nearestCity, CityDatabase.cityMap.values.toList().sortedBy { it.description }) {
minWidth = textWidth
styleClass += "city-picker"
@ -229,9 +229,9 @@ class NodeTabView : Fragment() {
if (it == null) error("Please select a city") else null
}
converter = object : StringConverter<PhysicalLocation>() {
override fun toString(loc: PhysicalLocation?) = loc?.description ?: ""
override fun fromString(string: String): PhysicalLocation? = CityDatabase[string]
converter = object : StringConverter<WorldMapLocation>() {
override fun toString(loc: WorldMapLocation?) = loc?.description ?: ""
override fun fromString(string: String): WorldMapLocation? = CityDatabase[string]
}
value = CityDatabase["London"]

View File

@ -98,7 +98,7 @@ class Network : CordaView() {
copyableLabel(SimpleObjectProperty(node.legalIdentity.owningKey.toBase58String())).apply { minWidth = 400.0 }
}
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 {
@ -122,7 +122,7 @@ class Network : CordaView() {
contentDisplay = ContentDisplay.TOP
val coordinate = Bindings.createObjectBinding({
// 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()))
// Center point of the label.
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.crypto.*
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty
import net.corda.core.node.NodeInfo
import net.corda.explorer.AmountDiff
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.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.crypto.commonName
import net.corda.core.flows.FlowException
import net.corda.core.getOrThrow
import net.corda.core.messaging.startFlow