mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
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:
parent
4139cf497d
commit
58da76c052
@ -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 }
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
----------
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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>(),
|
||||
|
@ -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.
|
||||
|
@ -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") { _, _ ->
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -64,4 +64,4 @@ object UpdateBusinessDayFlow {
|
||||
send(recipient.legalIdentity, UpdateBusinessDayMessage(date))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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"]
|
||||
|
@ -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 })
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user