mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Remove advertised services from NodeInfo (#1521)
* Remove advertisedServices from NodeInfo. Introduce notaryIdentities in NetworkMapCache, that will be filled in later from NetworkParameters. Clean up NetworkMapCache API. Expose notaryIdentities through RPC. For now we assume as temporary solution that notaries in NetworkMap have to contain "notary" in name. * Further clean up of NetworkMapCache API Remve partyNodes. Introduce getAllNodeInfos function * Remove notaryIdentity from ServiceHub * Address Shams review comments * Address Andrius review comments * Add comments, cleanup * Fixes * Address comments * Yet another commit with comments addressed * Move ServiceType and ServiceInfo to node-api Add changelog entry. Address rest of comments. * Minor comments
This commit is contained in:
parent
6887947a4d
commit
fd57cf1c0c
@ -9,6 +9,7 @@ import net.corda.core.crypto.keys
|
||||
import net.corda.core.flows.FlowInitiator
|
||||
import net.corda.core.flows.StateMachineRunId
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.bufferUntilSubscribed
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.messaging.StateMachineTransactionMapping
|
||||
@ -16,7 +17,6 @@ import net.corda.core.messaging.StateMachineUpdate
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.NetworkMapCache
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.Vault
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
@ -27,7 +27,7 @@ import net.corda.finance.flows.CashExitFlow
|
||||
import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.*
|
||||
@ -39,7 +39,7 @@ import rx.Observable
|
||||
class NodeMonitorModelTest : DriverBasedTest() {
|
||||
lateinit var aliceNode: NodeInfo
|
||||
lateinit var bobNode: NodeInfo
|
||||
lateinit var notaryNode: NodeInfo
|
||||
lateinit var notaryParty: Party
|
||||
|
||||
lateinit var rpc: CordaRPCOps
|
||||
lateinit var rpcBob: CordaRPCOps
|
||||
@ -59,11 +59,9 @@ class NodeMonitorModelTest : DriverBasedTest() {
|
||||
startFlowPermission<CashExitFlow>())
|
||||
)
|
||||
val aliceNodeFuture = startNode(providedName = ALICE.name, rpcUsers = listOf(cashUser))
|
||||
val notaryNodeFuture = startNode(providedName = DUMMY_NOTARY.name, advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type)))
|
||||
val notaryHandle = startNode(providedName = DUMMY_NOTARY.name, advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type))).getOrThrow()
|
||||
val aliceNodeHandle = aliceNodeFuture.getOrThrow()
|
||||
val notaryNodeHandle = notaryNodeFuture.getOrThrow()
|
||||
aliceNode = aliceNodeHandle.nodeInfo
|
||||
notaryNode = notaryNodeHandle.nodeInfo
|
||||
newNode = { nodeName -> startNode(providedName = nodeName).getOrThrow().nodeInfo }
|
||||
val monitor = NodeMonitorModel()
|
||||
stateMachineTransactionMapping = monitor.stateMachineTransactionMapping.bufferUntilSubscribed()
|
||||
@ -75,6 +73,7 @@ class NodeMonitorModelTest : DriverBasedTest() {
|
||||
|
||||
monitor.register(aliceNodeHandle.configuration.rpcAddress!!, cashUser.username, cashUser.password, initialiseSerialization = false)
|
||||
rpc = monitor.proxyObservable.value!!
|
||||
notaryParty = notaryHandle.nodeInfo.legalIdentities[1]
|
||||
|
||||
val bobNodeHandle = startNode(providedName = BOB.name, rpcUsers = listOf(cashUser)).getOrThrow()
|
||||
bobNode = bobNodeHandle.nodeInfo
|
||||
@ -87,9 +86,9 @@ class NodeMonitorModelTest : DriverBasedTest() {
|
||||
|
||||
@Test
|
||||
fun `network map update`() {
|
||||
newNode(CHARLIE.name)
|
||||
networkMapUpdates.filter { !it.node.advertisedServices.any { it.info.type.isNotary() } }
|
||||
.filter { !it.node.advertisedServices.any { it.info.type == NetworkMapService.type } }
|
||||
val charlieNode = newNode(CHARLIE.name)
|
||||
val nonServiceIdentities = aliceNode.legalIdentitiesAndCerts + bobNode.legalIdentitiesAndCerts + charlieNode.legalIdentitiesAndCerts
|
||||
networkMapUpdates.filter { it.node.legalIdentitiesAndCerts.any { it in nonServiceIdentities } }
|
||||
.expectEvents(isStrict = false) {
|
||||
sequence(
|
||||
// TODO : Add test for remove when driver DSL support individual node shutdown.
|
||||
@ -111,7 +110,7 @@ class NodeMonitorModelTest : DriverBasedTest() {
|
||||
rpc.startFlow(::CashIssueFlow,
|
||||
Amount(100, USD),
|
||||
OpaqueBytes(ByteArray(1, { 1 })),
|
||||
notaryNode.notaryIdentity
|
||||
notaryParty
|
||||
)
|
||||
|
||||
vaultUpdates.expectEvents(isStrict = false) {
|
||||
@ -132,7 +131,7 @@ class NodeMonitorModelTest : DriverBasedTest() {
|
||||
|
||||
@Test
|
||||
fun `cash issue and move`() {
|
||||
val (_, issueIdentity) = rpc.startFlow(::CashIssueFlow, 100.DOLLARS, OpaqueBytes.of(1), notaryNode.notaryIdentity).returnValue.getOrThrow()
|
||||
val (_, issueIdentity) = rpc.startFlow(::CashIssueFlow, 100.DOLLARS, OpaqueBytes.of(1), notaryParty).returnValue.getOrThrow()
|
||||
rpc.startFlow(::CashPaymentFlow, 100.DOLLARS, bobNode.chooseIdentity()).returnValue.getOrThrow()
|
||||
|
||||
var issueSmId: StateMachineRunId? = null
|
||||
@ -191,7 +190,7 @@ class NodeMonitorModelTest : DriverBasedTest() {
|
||||
val signaturePubKeys = stx.sigs.map { it.by }.toSet()
|
||||
// Alice and Notary signed
|
||||
require(issueIdentity!!.owningKey.isFulfilledBy(signaturePubKeys))
|
||||
require(notaryNode.notaryIdentity.owningKey.isFulfilledBy(signaturePubKeys))
|
||||
require(notaryParty.owningKey.isFulfilledBy(signaturePubKeys))
|
||||
moveTx = stx
|
||||
}
|
||||
)
|
||||
|
@ -7,8 +7,8 @@ import javafx.collections.FXCollections
|
||||
import javafx.collections.ObservableList
|
||||
import net.corda.client.jfx.utils.fold
|
||||
import net.corda.client.jfx.utils.map
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.AnonymousParty
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.NetworkMapCache.MapChange
|
||||
import java.security.PublicKey
|
||||
@ -33,25 +33,13 @@ class NetworkIdentityModel {
|
||||
private val identityCache = CacheBuilder.newBuilder()
|
||||
.build<PublicKey, ObservableValue<NodeInfo?>>(CacheLoader.from {
|
||||
publicKey ->
|
||||
publicKey?.let { rpcProxy.map { it?.nodeIdentityFromParty(AnonymousParty(publicKey)) } }
|
||||
publicKey?.let { rpcProxy.map { it?.nodeInfoFromParty(AnonymousParty(publicKey)) } }
|
||||
})
|
||||
|
||||
val parties: ObservableList<NodeInfo> = networkIdentities.filtered { !it.isCordaService() }
|
||||
val notaries: ObservableList<NodeInfo> = networkIdentities.filtered { it.advertisedServices.any { it.info.type.isNotary() } }
|
||||
val myNodeInfo = rpcProxy.map { it?.nodeInfo() } // TODO Used only for querying for advertised services, remove with services.
|
||||
val myIdentity = myNodeInfo.map { it?.legalIdentitiesAndCerts?.first()?.party }
|
||||
|
||||
private fun NodeInfo.isCordaService(): Boolean {
|
||||
// TODO: better way to identify Corda service?
|
||||
return advertisedServices.any { it.info.type.isNetworkMap() || it.info.type.isNotary() }
|
||||
}
|
||||
val notaries: ObservableList<PartyAndCertificate> = FXCollections.observableList(rpcProxy.value?.notaryIdentities())
|
||||
val notaryNodes: ObservableList<NodeInfo> = FXCollections.observableList(notaries.map { rpcProxy.value?.nodeInfoFromParty(it.party) })
|
||||
val parties: ObservableList<NodeInfo> = networkIdentities.filtered { it.legalIdentitiesAndCerts.all { it !in notaries } }
|
||||
val myIdentity = rpcProxy.map { it?.nodeInfo()?.legalIdentitiesAndCerts?.first()?.party }
|
||||
|
||||
fun partyFromPublicKey(publicKey: PublicKey): ObservableValue<NodeInfo?> = identityCache[publicKey]
|
||||
//TODO rebase fix
|
||||
// // TODO: Use Identity Service in service hub instead?
|
||||
// fun lookup(publicKey: PublicKey): ObservableValue<PartyAndCertificate?> {
|
||||
// val party = parties.flatMap { it.legalIdentitiesAndCerts }.firstOrNull { publicKey in it.owningKey.keys } ?:
|
||||
// notaries.flatMap { it.legalIdentitiesAndCerts }.firstOrNull { it.owningKey.keys.any { it == publicKey }}
|
||||
// return ReadOnlyObjectWrapper(party)
|
||||
// }
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import net.corda.client.rpc.CordaRPCClient
|
||||
import net.corda.client.rpc.CordaRPCClientConfiguration
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.flows.StateMachineRunId
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.messaging.*
|
||||
import net.corda.core.node.services.NetworkMapCache.MapChange
|
||||
import net.corda.core.node.services.Vault
|
||||
@ -45,6 +46,7 @@ class NodeMonitorModel {
|
||||
val networkMap: Observable<MapChange> = networkMapSubject
|
||||
|
||||
val proxyObservable = SimpleObjectProperty<CordaRPCOps?>()
|
||||
lateinit var notaryIdentities: List<PartyAndCertificate>
|
||||
|
||||
/**
|
||||
* Register for updates to/from a given vault.
|
||||
@ -60,6 +62,7 @@ class NodeMonitorModel {
|
||||
)
|
||||
val connection = client.start(username, password)
|
||||
val proxy = connection.proxy
|
||||
notaryIdentities = proxy.notaryIdentities()
|
||||
|
||||
val (stateMachines, stateMachineUpdates) = proxy.stateMachinesFeed()
|
||||
// Extract the flow tracking stream
|
||||
|
@ -5,7 +5,6 @@ import net.corda.core.concurrent.CordaFuture;
|
||||
import net.corda.core.contracts.Amount;
|
||||
import net.corda.core.messaging.CordaRPCOps;
|
||||
import net.corda.core.messaging.FlowHandle;
|
||||
import net.corda.core.node.services.ServiceInfo;
|
||||
import net.corda.core.utilities.OpaqueBytes;
|
||||
import net.corda.finance.flows.AbstractCashFlow;
|
||||
import net.corda.finance.flows.CashIssueFlow;
|
||||
@ -14,6 +13,7 @@ import net.corda.finance.schemas.*;
|
||||
import net.corda.node.internal.Node;
|
||||
import net.corda.node.internal.StartedNode;
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService;
|
||||
import net.corda.nodeapi.ServiceInfo;
|
||||
import net.corda.nodeapi.User;
|
||||
import net.corda.testing.CoreTestUtils;
|
||||
import net.corda.testing.node.NodeBasedTest;
|
||||
|
@ -6,7 +6,6 @@ import net.corda.core.messaging.FlowProgressHandle
|
||||
import net.corda.core.messaging.StateMachineUpdate
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.messaging.startTrackedFlow
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.finance.DOLLARS
|
||||
@ -20,6 +19,7 @@ import net.corda.finance.schemas.CashSchemaV1
|
||||
import net.corda.node.internal.Node
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.ALICE
|
||||
|
@ -9,6 +9,7 @@ import net.corda.core.flows.StateMachineRunId
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.NetworkMapCache
|
||||
import net.corda.core.node.services.Vault
|
||||
@ -212,6 +213,11 @@ interface CordaRPCOps : RPCOps {
|
||||
*/
|
||||
fun nodeInfo(): NodeInfo
|
||||
|
||||
/**
|
||||
* Returns network's notary identities, assuming this will not change while the node is running.
|
||||
*/
|
||||
fun notaryIdentities(): List<PartyAndCertificate>
|
||||
|
||||
/*
|
||||
* Add note(s) to an existing Vault transaction
|
||||
*/
|
||||
@ -284,11 +290,11 @@ interface CordaRPCOps : RPCOps {
|
||||
fun registeredFlows(): List<String>
|
||||
|
||||
/**
|
||||
* Returns a node's identity from the network map cache, where known.
|
||||
* Returns a node's info from the network map cache, where known.
|
||||
*
|
||||
* @return the node info if available.
|
||||
*/
|
||||
fun nodeIdentityFromParty(party: AbstractParty): NodeInfo?
|
||||
fun nodeInfoFromParty(party: AbstractParty): NodeInfo?
|
||||
|
||||
/**
|
||||
* Clear all network map data from local node cache.
|
||||
|
@ -2,37 +2,24 @@ package net.corda.core.node
|
||||
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
|
||||
/**
|
||||
* Information for an advertised service including the service specific identity information.
|
||||
* The identity can be used in flows and is distinct from the Node's legalIdentity
|
||||
*/
|
||||
@CordaSerializable
|
||||
data class ServiceEntry(val info: ServiceInfo, val identity: PartyAndCertificate)
|
||||
|
||||
/**
|
||||
* Info about a network node that acts on behalf of some form of contract party.
|
||||
* @param legalIdentitiesAndCerts is a non-empty list, where the first identity is assumed to be the default identity of the node.
|
||||
*/
|
||||
// TODO We currently don't support multi-IP/multi-identity nodes, we only left slots in the data structures.
|
||||
@CordaSerializable
|
||||
data class NodeInfo(val addresses: List<NetworkHostAndPort>,
|
||||
/** Non-empty list of all the identities, plus certificates, that belong to this node. */
|
||||
val legalIdentitiesAndCerts: List<PartyAndCertificate>,
|
||||
val platformVersion: Int,
|
||||
val advertisedServices: List<ServiceEntry> = emptyList(),
|
||||
val serial: Long
|
||||
) {
|
||||
init {
|
||||
require(legalIdentitiesAndCerts.isNotEmpty()) { "Node should have at least one legal identity" }
|
||||
}
|
||||
|
||||
// TODO This part will be removed with services removal.
|
||||
val notaryIdentity: Party get() = advertisedServices.single { it.info.type.isNotary() }.identity.party
|
||||
|
||||
@Transient private var _legalIdentities: List<Party>? = null
|
||||
val legalIdentities: List<Party> get() {
|
||||
return _legalIdentities ?: legalIdentitiesAndCerts.map { it.party }.also { _legalIdentities = it }
|
||||
@ -40,8 +27,4 @@ data class NodeInfo(val addresses: List<NetworkHostAndPort>,
|
||||
|
||||
/** Returns true if [party] is one of the identities of this node, else false. */
|
||||
fun isLegalIdentity(party: Party): Boolean = party in legalIdentities
|
||||
|
||||
fun serviceIdentities(type: ServiceType): List<Party> {
|
||||
return advertisedServices.mapNotNull { if (it.info.type.isSubTypeOf(type)) it.identity.party else null }
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +143,9 @@ interface ServiceHub : ServicesForResolution {
|
||||
* If the key is actually a [net.corda.core.crypto.CompositeKey], the first leaf key hosted on this node
|
||||
* will be used to create the signature.
|
||||
*/
|
||||
val notaryIdentityKey: PublicKey get() = this.myInfo.notaryIdentity.owningKey
|
||||
// TODO Remove that from ServiceHub, we could take that information from a transaction notary field and figure out what key to use from that.
|
||||
// But, it's separate PR.
|
||||
val notaryIdentityKey: PublicKey
|
||||
|
||||
// Helper method to construct an initial partially signed transaction from a [TransactionBuilder].
|
||||
private fun signInitialTransaction(builder: TransactionBuilder, publicKey: PublicKey, signatureMetadata: SignatureMetadata): SignedTransaction {
|
||||
|
@ -5,10 +5,10 @@ import net.corda.core.contracts.Contract
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.internal.randomOrNull
|
||||
import net.corda.core.messaging.DataFeed
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.ServiceEntry
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import rx.Observable
|
||||
@ -31,18 +31,9 @@ interface NetworkMapCache {
|
||||
data class Modified(override val node: NodeInfo, val previousNode: NodeInfo) : MapChange()
|
||||
}
|
||||
|
||||
/** A list of all nodes the cache is aware of */
|
||||
val partyNodes: List<NodeInfo>
|
||||
/** A list of nodes that advertise a network map service */
|
||||
val networkMapNodes: List<NodeInfo>
|
||||
/** A list of nodes that advertise a notary service */
|
||||
val notaryNodes: List<NodeInfo> get() = getNodesWithService(ServiceType.notary)
|
||||
/**
|
||||
* A list of nodes that advertise a regulatory service. Identifying the correct regulator for a trade is outside
|
||||
* the scope of the network map service, and this is intended solely as a sanity check on configuration stored
|
||||
* elsewhere.
|
||||
*/
|
||||
val regulatorNodes: List<NodeInfo> get() = getNodesWithService(ServiceType.regulator)
|
||||
/** A list of notary services available on the network */
|
||||
// TODO this list will be taken from NetworkParameters distributed by NetworkMap.
|
||||
val notaryIdentities: List<PartyAndCertificate>
|
||||
/** Tracks changes to the network map cache */
|
||||
val changed: Observable<MapChange>
|
||||
/** Future to track completion of the NetworkMapService registration. */
|
||||
@ -54,26 +45,6 @@ interface NetworkMapCache {
|
||||
*/
|
||||
fun track(): DataFeed<List<NodeInfo>, MapChange>
|
||||
|
||||
/** Get the collection of nodes which advertise a specific service. */
|
||||
fun getNodesWithService(serviceType: ServiceType): List<NodeInfo> {
|
||||
return partyNodes.filter { it.advertisedServices.any { it.info.type.isSubTypeOf(serviceType) } }
|
||||
}
|
||||
|
||||
// TODO It will be removed with services + part of these functions will get merged into database backed NetworkMapCache
|
||||
fun getPeersWithService(serviceType: ServiceType): List<ServiceEntry> {
|
||||
return partyNodes.fold(ArrayList<ServiceEntry>()) {
|
||||
acc, elem -> acc.addAll(elem.advertisedServices.filter { it.info.type.isSubTypeOf(serviceType)})
|
||||
acc
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a recommended node that advertises a service, and is suitable for the specified contract and parties.
|
||||
* Implementations might understand, for example, the correct regulator to use for specific contracts/parties,
|
||||
* or the appropriate oracle for a contract.
|
||||
*/
|
||||
fun getRecommended(type: ServiceType, contract: Contract, vararg party: Party): NodeInfo? = getNodesWithService(type).firstOrNull()
|
||||
|
||||
/**
|
||||
* Look up the node info for a specific party. Will attempt to de-anonymise the party if applicable; if the party
|
||||
* is anonymised and the well known party cannot be resolved, it is impossible ot identify the node and therefore this
|
||||
@ -86,81 +57,47 @@ interface NetworkMapCache {
|
||||
fun getNodeByLegalIdentity(party: AbstractParty): NodeInfo?
|
||||
|
||||
/** Look up the node info for a legal name. */
|
||||
fun getNodeByLegalName(principal: CordaX500Name): NodeInfo?
|
||||
fun getNodeByLegalName(name: CordaX500Name): NodeInfo?
|
||||
|
||||
/** Look up the node info for a host and port. */
|
||||
fun getNodeByAddress(address: NetworkHostAndPort): NodeInfo?
|
||||
|
||||
fun getPeerByLegalName(principal: CordaX500Name): Party? = getNodeByLegalName(principal)?.let {
|
||||
it.legalIdentitiesAndCerts.singleOrNull { it.name == principal }?.party
|
||||
fun getPeerByLegalName(name: CordaX500Name): Party? = getNodeByLegalName(name)?.let {
|
||||
it.legalIdentitiesAndCerts.singleOrNull { it.name == name }?.party
|
||||
}
|
||||
|
||||
/** Return all [NodeInfo]s the node currently is aware of (including ourselves). */
|
||||
val allNodes: List<NodeInfo>
|
||||
|
||||
/**
|
||||
* Look up the node infos for a specific peer key.
|
||||
* In general, nodes can advertise multiple identities: a legal identity, and separate identities for each of
|
||||
* the services it provides. In case of a distributed service – run by multiple nodes – each participant advertises
|
||||
* the identity of the *whole group*.
|
||||
*/
|
||||
/** Look up the node infos for a specific peer key. */
|
||||
fun getNodesByLegalIdentityKey(identityKey: PublicKey): List<NodeInfo>
|
||||
|
||||
/** Look up all nodes advertising the service owned by [publicKey] */
|
||||
fun getNodesByAdvertisedServiceIdentityKey(publicKey: PublicKey): List<NodeInfo> {
|
||||
return partyNodes.filter { it.advertisedServices.any { it.identity.owningKey == publicKey } }
|
||||
}
|
||||
|
||||
/** Returns information about the party, which may be a specific node or a service */
|
||||
fun getPartyInfo(party: Party): PartyInfo?
|
||||
|
||||
/** Gets a notary identity by the given name. */
|
||||
fun getNotary(principal: CordaX500Name): Party? {
|
||||
val notaryNode = notaryNodes.filter {
|
||||
it.advertisedServices.any { it.info.type.isSubTypeOf(ServiceType.notary) && it.info.name == principal }
|
||||
}.randomOrNull()
|
||||
return notaryNode?.notaryIdentity
|
||||
}
|
||||
fun getNotary(name: CordaX500Name): Party? = notaryIdentities.firstOrNull { it.name == name }?.party
|
||||
|
||||
/**
|
||||
* Returns a notary identity advertised by any of the nodes on the network (chosen at random)
|
||||
* @param type Limits the result to notaries of the specified type (optional)
|
||||
*/
|
||||
fun getAnyNotary(type: ServiceType? = null): Party? {
|
||||
val nodes = if (type == null) {
|
||||
notaryNodes
|
||||
} else {
|
||||
require(type != ServiceType.notary && type.isSubTypeOf(ServiceType.notary)) {
|
||||
"The provided type must be a specific notary sub-type"
|
||||
}
|
||||
notaryNodes.filter { it.advertisedServices.any { it.info.type == type } }
|
||||
}
|
||||
return nodes.randomOrNull()?.notaryIdentity
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a service identity advertised by one of the nodes on the network
|
||||
* @param type Specifies the type of the service
|
||||
*/
|
||||
fun getAnyServiceOfType(type: ServiceType): Party? {
|
||||
for (node in partyNodes) {
|
||||
val serviceIdentities = node.serviceIdentities(type)
|
||||
if (serviceIdentities.isNotEmpty()) {
|
||||
return serviceIdentities.randomOrNull()
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
fun getAnyNotary(): Party? = notaryIdentities.randomOrNull()?.party
|
||||
|
||||
/** Checks whether a given party is an advertised notary identity */
|
||||
fun isNotary(party: Party): Boolean = notaryNodes.any { it.notaryIdentity == party }
|
||||
fun isNotary(party: Party): Boolean = notaryIdentities.any { party == it.party }
|
||||
|
||||
/** Checks whether a given party is an advertised validating notary identity */
|
||||
/** Checks whether a given party is an validating notary identity */
|
||||
fun isValidatingNotary(party: Party): Boolean {
|
||||
val notary = notaryNodes.firstOrNull { it.notaryIdentity == party }
|
||||
?: throw IllegalArgumentException("No notary found with identity $party. This is most likely caused " +
|
||||
"by using the notary node's legal identity instead of its advertised notary identity. " +
|
||||
"Your options are: ${notaryNodes.map { "\"${it.notaryIdentity.name}\"" }.joinToString()}.")
|
||||
return notary.advertisedServices.any { it.info.type.isValidatingNotary() }
|
||||
val notary = notaryIdentities.firstOrNull { it.party == party } ?:
|
||||
throw IllegalArgumentException("No notary found with identity $party.")
|
||||
return !notary.name.toString().contains("corda.notary.simple", true) // TODO This implementation will change after introducing of NetworkParameters.
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all network map data from local node cache.
|
||||
*/
|
||||
|
@ -2,7 +2,6 @@ package net.corda.core.schemas
|
||||
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.ServiceEntry
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
@ -39,10 +38,6 @@ object NodeInfoSchemaV1 : MappedSchema(
|
||||
@Column(name = "platform_version")
|
||||
val platformVersion: Int,
|
||||
|
||||
@Column(name = "advertised_services")
|
||||
@ElementCollection
|
||||
var advertisedServices: List<DBServiceEntry> = emptyList(),
|
||||
|
||||
/**
|
||||
* serial is an increasing value which represents the version of [NodeInfo].
|
||||
* Not expected to be sequential, but later versions of the registration must have higher values
|
||||
@ -56,9 +51,6 @@ object NodeInfoSchemaV1 : MappedSchema(
|
||||
this.addresses.map { it.toHostAndPort() },
|
||||
(this.legalIdentitiesAndCerts.filter { it.isMain } + this.legalIdentitiesAndCerts.filter { !it.isMain }).map { it.toLegalIdentityAndCert() },
|
||||
this.platformVersion,
|
||||
this.advertisedServices.map {
|
||||
it.serviceEntry?.deserialize<ServiceEntry>() ?: throw IllegalStateException("Service entry shouldn't be null")
|
||||
},
|
||||
this.serial
|
||||
)
|
||||
}
|
||||
@ -85,12 +77,6 @@ object NodeInfoSchemaV1 : MappedSchema(
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable // TODO To be removed with services.
|
||||
data class DBServiceEntry(
|
||||
@Column(length = 65535)
|
||||
val serviceEntry: ByteArray? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* PartyAndCertificate entity (to be replaced by referencing final Identity Schema).
|
||||
*/
|
||||
|
@ -8,9 +8,9 @@ import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.FetchAttachmentsFlow
|
||||
import net.corda.core.internal.FetchDataFlow
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.persistence.NodeAttachmentService
|
||||
|
@ -16,6 +16,7 @@ import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.chooseIdentityAndCert
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.After
|
||||
@ -39,8 +40,8 @@ class CollectSignaturesFlowTests {
|
||||
a = nodes.partyNodes[0]
|
||||
b = nodes.partyNodes[1]
|
||||
c = nodes.partyNodes[2]
|
||||
notary = nodes.notaryNode.info.notaryIdentity
|
||||
mockNet.runNetwork()
|
||||
notary = a.services.getDefaultNotary()
|
||||
a.internals.ensureRegistered()
|
||||
}
|
||||
|
||||
@ -86,7 +87,7 @@ class CollectSignaturesFlowTests {
|
||||
@Suspendable
|
||||
override fun call(): SignedTransaction {
|
||||
val state = receive<DummyContract.MultiOwnerState>(otherParty).unwrap { it }
|
||||
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
|
||||
val notary = serviceHub.getDefaultNotary()
|
||||
|
||||
val myInputKeys = state.participants.map { it.owningKey }
|
||||
val myKeys = myInputKeys + (identities[ourIdentity] ?: ourIdentity).owningKey
|
||||
@ -107,7 +108,7 @@ class CollectSignaturesFlowTests {
|
||||
class Initiator(val state: DummyContract.MultiOwnerState) : FlowLogic<SignedTransaction>() {
|
||||
@Suspendable
|
||||
override fun call(): SignedTransaction {
|
||||
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
|
||||
val notary = serviceHub.getDefaultNotary()
|
||||
val myInputKeys = state.participants.map { it.owningKey }
|
||||
val command = Command(DummyContract.Commands.Create(), myInputKeys)
|
||||
val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), command)
|
||||
|
@ -25,6 +25,7 @@ import net.corda.testing.RPCDriverExposedDSLInterface
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.contracts.DummyContractV2
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.rpcDriver
|
||||
import net.corda.testing.rpcTestUser
|
||||
@ -54,9 +55,8 @@ class ContractUpgradeFlowTest {
|
||||
mockNet.runNetwork()
|
||||
a.internals.ensureRegistered()
|
||||
|
||||
notary = nodes.notaryNode.info.notaryIdentity
|
||||
|
||||
val nodeIdentity = nodes.notaryNode.info.legalIdentitiesAndCerts.single { it.party == nodes.notaryNode.info.notaryIdentity }
|
||||
notary = a.services.getDefaultNotary()
|
||||
val nodeIdentity = nodes.notaryNode.info.legalIdentitiesAndCerts.single { it.party == notary }
|
||||
a.database.transaction {
|
||||
a.services.identityService.verifyAndRegisterIdentity(nodeIdentity)
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.After
|
||||
@ -31,9 +32,9 @@ class FinalityFlowTests {
|
||||
val nodes = mockNet.createSomeNodes(2)
|
||||
nodeA = nodes.partyNodes[0]
|
||||
nodeB = nodes.partyNodes[1]
|
||||
notary = nodes.notaryNode.info.notaryIdentity
|
||||
mockNet.runNetwork()
|
||||
nodeA.internals.ensureRegistered()
|
||||
notary = nodeA.services.getDefaultNotary()
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -13,6 +13,7 @@ import net.corda.testing.ALICE
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@ -47,7 +48,8 @@ class IdentitySyncFlowTests {
|
||||
// Alice issues then pays some cash to a new confidential identity that Bob doesn't know about
|
||||
val anonymous = true
|
||||
val ref = OpaqueBytes.of(0x01)
|
||||
val issueFlow = aliceNode.services.startFlow(CashIssueAndPaymentFlow(1000.DOLLARS, ref, alice, anonymous, notaryNode.services.myInfo.notaryIdentity))
|
||||
val notary = aliceNode.services.getDefaultNotary()
|
||||
val issueFlow = aliceNode.services.startFlow(CashIssueAndPaymentFlow(1000.DOLLARS, ref, alice, anonymous, notary))
|
||||
val issueTx = issueFlow.resultFuture.getOrThrow().stx
|
||||
val confidentialIdentity = issueTx.tx.outputs.map { it.data }.filterIsInstance<Cash.State>().single().owner
|
||||
assertNull(bobNode.database.transaction { bobNode.services.identityService.partyFromAnonymous(confidentialIdentity) })
|
||||
|
@ -9,6 +9,7 @@ import net.corda.finance.GBP
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.After
|
||||
@ -32,9 +33,9 @@ class ManualFinalityFlowTests {
|
||||
nodeA = nodes.partyNodes[0]
|
||||
nodeB = nodes.partyNodes[1]
|
||||
nodeC = nodes.partyNodes[2]
|
||||
notary = nodes.notaryNode.info.notaryIdentity
|
||||
mockNet.runNetwork()
|
||||
nodeA.internals.ensureRegistered()
|
||||
notary = nodeA.services.getDefaultNotary()
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -17,6 +17,7 @@ import net.corda.testing.MEGA_CORP_KEY
|
||||
import net.corda.testing.MINI_CORP
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.After
|
||||
@ -47,8 +48,8 @@ class ResolveTransactionsFlowTest {
|
||||
b = nodes.partyNodes[1]
|
||||
a.internals.registerInitiatedFlow(TestResponseFlow::class.java)
|
||||
b.internals.registerInitiatedFlow(TestResponseFlow::class.java)
|
||||
notary = nodes.notaryNode.info.notaryIdentity
|
||||
mockNet.runNetwork()
|
||||
notary = a.services.getDefaultNotary()
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -1,38 +0,0 @@
|
||||
package net.corda.core.node
|
||||
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
class ServiceInfoTests {
|
||||
val serviceType = ServiceType.getServiceType("test", "service").getSubType("subservice")
|
||||
val name = CordaX500Name(organisation = "Service.name", locality = "London", country = "GB")
|
||||
|
||||
@Test
|
||||
fun `type and name encodes correctly`() {
|
||||
assertEquals(ServiceInfo(serviceType, name).toString(), "$serviceType|$name")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `type and name parses correctly`() {
|
||||
assertEquals(ServiceInfo.parse("$serviceType|$name"), ServiceInfo(serviceType, name))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `type only encodes correctly`() {
|
||||
assertEquals(ServiceInfo(serviceType).toString(), "$serviceType")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `type only parses correctly`() {
|
||||
assertEquals(ServiceInfo.parse("$serviceType"), ServiceInfo(serviceType))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `invalid encoding throws`() {
|
||||
assertFailsWith<IllegalArgumentException> { ServiceInfo.parse("$serviceType|$name|something") }
|
||||
}
|
||||
}
|
@ -10,11 +10,11 @@ import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.FetchAttachmentsFlow
|
||||
import net.corda.core.internal.FetchDataFlow
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.node.internal.InitiatedFlowFactory
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.persistence.NodeAttachmentService
|
||||
|
@ -6,6 +6,19 @@ from the previous milestone release.
|
||||
|
||||
UNRELEASED
|
||||
----------
|
||||
* ``NodeInfo`` and ``NetworkMapCache`` changes:
|
||||
* Removed ``NodeInfo::legalIdentity`` in preparation for handling of multiple identities. We left list of ``NodeInfo::legalIdentitiesAndCerts``,
|
||||
the first identity still plays a special role of main node identity.
|
||||
* We no longer support advertising services in network map. Removed ``NodeInfo::advertisedServices``, ``serviceIdentities``
|
||||
and ``notaryIdentity``.
|
||||
* Removed service methods from ``NetworkMapCache``: ``partyNodes``, ``networkMapNodes``, ``notaryNodes``, ``regulatorNodes``,
|
||||
``getNodesWithService``, ``getPeersWithService``, ``getRecommended``, ``getNodesByAdvertisedServiceIdentityKey``,
|
||||
``notaryNode``, ``getAnyServiceOfType``. To get all known ``NodeInfo``s call ``allNodes``.
|
||||
* In preparation for ``NetworkMapService`` redesign and distributing notaries through ``NetworkParameters`` we added
|
||||
``NetworkMapCache::notaryIdentities`` list to enable to lookup for notary parties known to the network. Related ``CordaRPCOps::notaryIdentities``
|
||||
was introduced. Other special nodes parties like Oracles or Regulators need to be specified directly in CorDapp or flow.
|
||||
* Moved ``ServiceType`` and ``ServiceInfo`` to ``net.corda.nodeapi`` package as services are only required on node startup.
|
||||
|
||||
* Adding enum support to the class carpenter
|
||||
|
||||
* ``ContractState::contract`` has been moved ``TransactionState::contract`` and it's type has changed to ``String`` in order to
|
||||
|
@ -3,7 +3,6 @@ package net.corda.docs
|
||||
import net.corda.core.internal.concurrent.transpose
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.messaging.vaultTrackBy
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.Vault
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
@ -12,6 +11,7 @@ import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.*
|
||||
@ -56,11 +56,12 @@ class IntegrationTestingTutorial {
|
||||
|
||||
// START 4
|
||||
val issueRef = OpaqueBytes.of(0)
|
||||
val notaryParty = aliceProxy.notaryIdentities().first().party
|
||||
(1..10).map { i ->
|
||||
aliceProxy.startFlow(::CashIssueFlow,
|
||||
i.DOLLARS,
|
||||
issueRef,
|
||||
notary.nodeInfo.notaryIdentity
|
||||
notaryParty
|
||||
).returnValue
|
||||
}.transpose().getOrThrow()
|
||||
// We wait for all of the issuances to run before we start making payments
|
||||
|
@ -10,7 +10,6 @@ import net.corda.core.flows.*;
|
||||
import net.corda.core.identity.CordaX500Name;
|
||||
import net.corda.core.identity.Party;
|
||||
import net.corda.core.internal.FetchDataFlow;
|
||||
import net.corda.core.node.services.ServiceType;
|
||||
import net.corda.core.node.services.Vault;
|
||||
import net.corda.core.node.services.Vault.Page;
|
||||
import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria;
|
||||
@ -54,11 +53,13 @@ public class FlowCookbookJava {
|
||||
private final boolean arg1;
|
||||
private final int arg2;
|
||||
private final Party counterparty;
|
||||
private final Party regulator;
|
||||
|
||||
public InitiatorFlow(boolean arg1, int arg2, Party counterparty) {
|
||||
public InitiatorFlow(boolean arg1, int arg2, Party counterparty, Party regulator) {
|
||||
this.arg1 = arg1;
|
||||
this.arg2 = arg2;
|
||||
this.counterparty = counterparty;
|
||||
this.regulator = regulator;
|
||||
}
|
||||
|
||||
/*----------------------------------
|
||||
@ -124,11 +125,11 @@ public class FlowCookbookJava {
|
||||
// We retrieve a notary from the network map.
|
||||
// DOCSTART 1
|
||||
Party specificNotary = getServiceHub().getNetworkMapCache().getNotary(new CordaX500Name("Notary Service", "London", "UK"));
|
||||
Party anyNotary = getServiceHub().getNetworkMapCache().getAnyNotary(null);
|
||||
Party anyNotary = getServiceHub().getNetworkMapCache().getAnyNotary();
|
||||
// Unlike the first two methods, ``getNotaryNodes`` returns a
|
||||
// ``List<NodeInfo>``. We have to extract the notary identity of
|
||||
// the node we want.
|
||||
Party firstNotary = getServiceHub().getNetworkMapCache().getNotaryNodes().get(0).getNotaryIdentity();
|
||||
Party firstNotary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0).getParty();
|
||||
// DOCEND 1
|
||||
|
||||
// We may also need to identify a specific counterparty.
|
||||
@ -138,12 +139,6 @@ public class FlowCookbookJava {
|
||||
Party keyedCounterparty = getServiceHub().getIdentityService().partyFromKey(dummyPubKey);
|
||||
// DOCEND 2
|
||||
|
||||
// Finally, we can use the map to identify nodes providing a
|
||||
// specific service (e.g. a regulator or an oracle).
|
||||
// DOCSTART 3
|
||||
Party regulator = getServiceHub().getNetworkMapCache().getPeersWithService(ServiceType.Companion.getRegulator()).get(0).getIdentity().getParty();
|
||||
// DOCEND 3
|
||||
|
||||
/*------------------------------
|
||||
* SENDING AND RECEIVING DATA *
|
||||
------------------------------*/
|
||||
@ -528,7 +523,7 @@ public class FlowCookbookJava {
|
||||
// We can also choose to send it to additional parties who aren't one
|
||||
// of the state's participants.
|
||||
// DOCSTART 10
|
||||
Set<Party> additionalParties = ImmutableSet.of(regulator, regulator);
|
||||
Set<Party> additionalParties = ImmutableSet.of(regulator);
|
||||
SignedTransaction notarisedTx2 = subFlow(new FinalityFlow(ImmutableList.of(fullySignedTx), additionalParties, FINALISATION.childProgressTracker())).get(0);
|
||||
// DOCEND 10
|
||||
|
||||
|
@ -5,17 +5,18 @@ import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.messaging.vaultQueryBy
|
||||
import net.corda.core.node.CordaPluginRegistry
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.SerializationCustomization
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.finance.USD
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.flows.CashExitFlow
|
||||
import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.ALICE
|
||||
@ -56,6 +57,7 @@ fun main(args: Array<String>) {
|
||||
// START 2
|
||||
val client = node.rpcClientToNode()
|
||||
val proxy = client.start("user", "password").proxy
|
||||
proxy.waitUntilNetworkReady().getOrThrow()
|
||||
|
||||
thread {
|
||||
generateTransactions(proxy)
|
||||
@ -111,8 +113,7 @@ fun generateTransactions(proxy: CordaRPCOps) {
|
||||
sum + state.state.data.amount.quantity
|
||||
}
|
||||
val issueRef = OpaqueBytes.of(0)
|
||||
val parties = proxy.networkMapSnapshot()
|
||||
val notary = parties.first { it.advertisedServices.any { it.info.type.isNotary() } }.notaryIdentity
|
||||
val notary = proxy.notaryIdentities().first().party
|
||||
val me = proxy.nodeInfo().legalIdentities.first()
|
||||
while (true) {
|
||||
Thread.sleep(1000)
|
||||
|
@ -49,7 +49,7 @@ class MyValidatingNotaryFlow(otherSide: Party, service: MyCustomValidatingNotary
|
||||
|
||||
private fun checkSignatures(stx: SignedTransaction) {
|
||||
try {
|
||||
stx.verifySignaturesExcept(serviceHub.myInfo.notaryIdentity.owningKey)
|
||||
stx.verifySignaturesExcept(serviceHub.notaryIdentityKey)
|
||||
} catch (e: SignatureException) {
|
||||
throw NotaryException(NotaryError.TransactionInvalid(e))
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import net.corda.finance.flows.AbstractCashFlow
|
||||
import net.corda.finance.flows.CashException
|
||||
import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import java.util.*
|
||||
|
||||
// DOCSTART CustomVaultQuery
|
||||
@ -132,7 +133,7 @@ object TopupIssuerFlow {
|
||||
issueTo: Party,
|
||||
issuerPartyRef: OpaqueBytes): AbstractCashFlow.Result {
|
||||
// TODO: pass notary in as request parameter
|
||||
val notaryParty = serviceHub.networkMapCache.notaryNodes[0].notaryIdentity
|
||||
val notaryParty = serviceHub.networkMapCache.getAnyNotary() ?: throw IllegalArgumentException("Couldn't find any notary in NetworkMapCache")
|
||||
// invoke Cash subflow to issue Asset
|
||||
progressTracker.currentStep = ISSUING
|
||||
val issueCashFlow = CashIssueFlow(amount, issuerPartyRef, notaryParty)
|
||||
|
@ -10,7 +10,6 @@ import net.corda.core.flows.*
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.FetchDataFlow
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.node.services.Vault.Page
|
||||
import net.corda.core.node.services.queryBy
|
||||
import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria
|
||||
@ -40,7 +39,7 @@ object FlowCookbook {
|
||||
@StartableByRPC
|
||||
// Every flow must subclass ``FlowLogic``. The generic indicates the
|
||||
// flow's return type.
|
||||
class InitiatorFlow(val arg1: Boolean, val arg2: Int, val counterparty: Party) : FlowLogic<Unit>() {
|
||||
class InitiatorFlow(val arg1: Boolean, val arg2: Int, val counterparty: Party, val regulator: Party) : FlowLogic<Unit>() {
|
||||
|
||||
/**---------------------------------
|
||||
* WIRING UP THE PROGRESS TRACKER *
|
||||
@ -109,22 +108,18 @@ object FlowCookbook {
|
||||
// Unlike the first two methods, ``getNotaryNodes`` returns a
|
||||
// ``List<NodeInfo>``. We have to extract the notary identity of
|
||||
// the node we want.
|
||||
val firstNotary: Party = serviceHub.networkMapCache.notaryNodes[0].notaryIdentity
|
||||
val firstNotary: Party = serviceHub.networkMapCache.notaryIdentities[0].party
|
||||
// DOCEND 1
|
||||
|
||||
// We may also need to identify a specific counterparty. We
|
||||
// do so using identity service.
|
||||
// DOCSTART 2
|
||||
val namedCounterparty: Party? = serviceHub.identityService.partyFromX500Name(CordaX500Name(organisation = "NodeA", locality = "London", country = "UK"))
|
||||
val keyedCounterparty: Party? = serviceHub.identityService.partyFromKey(dummyPubKey)
|
||||
val namedCounterparty: Party = serviceHub.identityService.partyFromX500Name(CordaX500Name(organisation = "NodeA", locality = "London", country = "UK")) ?:
|
||||
throw IllegalArgumentException("Couldn't find counterparty for NodeA in identity service")
|
||||
val keyedCounterparty: Party = serviceHub.identityService.partyFromKey(dummyPubKey) ?:
|
||||
throw IllegalArgumentException("Couldn't find counterparty with key: $dummyPubKey in identity service")
|
||||
// DOCEND 2
|
||||
|
||||
// Finally, we can use the map to identify nodes providing a
|
||||
// specific service (e.g. a regulator or an oracle).
|
||||
// DOCSTART 3
|
||||
val regulator: Party = serviceHub.networkMapCache.getPeersWithService(ServiceType.regulator)[0].identity.party
|
||||
// DOCEND 3
|
||||
|
||||
/**-----------------------------
|
||||
* SENDING AND RECEIVING DATA *
|
||||
-----------------------------**/
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.corda.docs
|
||||
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.finance.*
|
||||
@ -9,11 +9,13 @@ import net.corda.finance.contracts.getCashBalances
|
||||
import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.finance.schemas.CashSchemaV1
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.DUMMY_NOTARY_KEY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Assert
|
||||
@ -27,6 +29,7 @@ class CustomVaultQueryTest {
|
||||
lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var nodeA: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var nodeB: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var notary: Party
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
@ -43,6 +46,7 @@ class CustomVaultQueryTest {
|
||||
nodeA.internals.installCordaService(CustomVaultQuery.Service::class.java)
|
||||
nodeA.internals.registerCustomSchemas(setOf(CashSchemaV1))
|
||||
nodeB.internals.registerCustomSchemas(setOf(CashSchemaV1))
|
||||
notary = nodeA.services.getDefaultNotary()
|
||||
}
|
||||
|
||||
@After
|
||||
@ -71,7 +75,7 @@ class CustomVaultQueryTest {
|
||||
// Use NodeA as issuer and create some dollars
|
||||
val flowHandle1 = nodeA.services.startFlow(CashIssueFlow(amountToIssue,
|
||||
OpaqueBytes.of(0x01),
|
||||
notaryNode.info.notaryIdentity))
|
||||
notary))
|
||||
// Wait for the flow to stop and print
|
||||
flowHandle1.resultFuture.getOrThrow()
|
||||
}
|
||||
@ -81,7 +85,7 @@ class CustomVaultQueryTest {
|
||||
nodeA.info.chooseIdentity(),
|
||||
OpaqueBytes.of(0x01),
|
||||
nodeA.info.chooseIdentity(),
|
||||
notaryNode.info.notaryIdentity))
|
||||
notary))
|
||||
flowHandle1.resultFuture.getOrThrow()
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
package net.corda.docs
|
||||
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.toFuture
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
@ -9,11 +9,13 @@ import net.corda.finance.contracts.getCashBalances
|
||||
import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.finance.schemas.CashSchemaV1
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.DUMMY_NOTARY_KEY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@ -25,6 +27,7 @@ class FxTransactionBuildTutorialTest {
|
||||
lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var nodeA: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var nodeB: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var notary: Party
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
@ -39,6 +42,7 @@ class FxTransactionBuildTutorialTest {
|
||||
nodeA.internals.registerCustomSchemas(setOf(CashSchemaV1))
|
||||
nodeB.internals.registerCustomSchemas(setOf(CashSchemaV1))
|
||||
nodeB.internals.registerInitiatedFlow(ForeignExchangeRemoteFlow::class.java)
|
||||
notary = nodeA.services.getDefaultNotary()
|
||||
}
|
||||
|
||||
@After
|
||||
@ -51,7 +55,7 @@ class FxTransactionBuildTutorialTest {
|
||||
// Use NodeA as issuer and create some dollars
|
||||
val flowHandle1 = nodeA.services.startFlow(CashIssueFlow(DOLLARS(1000),
|
||||
OpaqueBytes.of(0x01),
|
||||
notaryNode.info.notaryIdentity))
|
||||
notary))
|
||||
// Wait for the flow to stop and print
|
||||
flowHandle1.resultFuture.getOrThrow()
|
||||
printBalances()
|
||||
@ -59,7 +63,7 @@ class FxTransactionBuildTutorialTest {
|
||||
// Using NodeB as Issuer create some pounds.
|
||||
val flowHandle2 = nodeB.services.startFlow(CashIssueFlow(POUNDS(1000),
|
||||
OpaqueBytes.of(0x01),
|
||||
notaryNode.info.notaryIdentity))
|
||||
notary))
|
||||
// Wait for flow to come to an end and print
|
||||
flowHandle2.resultFuture.getOrThrow()
|
||||
printBalances()
|
||||
|
@ -4,12 +4,12 @@ import net.corda.core.contracts.LinearState
|
||||
import net.corda.core.contracts.StateAndRef
|
||||
import net.corda.core.contracts.UniqueIdentifier
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.queryBy
|
||||
import net.corda.core.node.services.vault.QueryCriteria
|
||||
import net.corda.core.toFuture
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
|
@ -331,7 +331,7 @@ the initiator then the buyer side would need to register their flow, perhaps wit
|
||||
services.registerServiceFlow(TwoPartyTradeFlow.Seller::class.java) {
|
||||
TwoPartyTradeFlow.Buyer(
|
||||
it,
|
||||
notary = services.networkMapCache.notaryNodes[0].notaryIdentity,
|
||||
notary = services.networkMapCache.notaryIdentities[0].party,
|
||||
acceptablePrice = TODO(),
|
||||
typeToBuy = TODO())
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ with this basic skeleton:
|
||||
val nodes = mockNet.createSomeNodes()
|
||||
a = nodes.partyNodes[0]
|
||||
b = nodes.partyNodes[1]
|
||||
notary = nodes.notaryNode.info.notaryIdentity
|
||||
mockNet.runNetwork()
|
||||
notary = a.services.getDefaultNotary()
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -11,8 +11,6 @@ import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.SignTransactionFlow
|
||||
import net.corda.core.identity.AnonymousParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
@ -51,7 +49,7 @@ object TwoPartyDealFlow {
|
||||
}
|
||||
|
||||
abstract val payload: Any
|
||||
abstract val notaryNode: NodeInfo
|
||||
abstract val notaryParty: Party
|
||||
abstract val otherParty: Party
|
||||
|
||||
@Suspendable override fun call(): SignedTransaction {
|
||||
@ -82,7 +80,8 @@ object TwoPartyDealFlow {
|
||||
/**
|
||||
* Abstracted bilateral deal flow participant that is recipient of initial communication.
|
||||
*/
|
||||
abstract class Secondary<U>(override val progressTracker: ProgressTracker = Secondary.tracker()) : FlowLogic<SignedTransaction>() {
|
||||
abstract class Secondary<U>(override val progressTracker: ProgressTracker = Secondary.tracker(),
|
||||
val regulators: List<Party> = emptyList()) : FlowLogic<SignedTransaction>() {
|
||||
|
||||
companion object {
|
||||
object RECEIVING : ProgressTracker.Step("Waiting for deal info.")
|
||||
@ -126,12 +125,10 @@ object TwoPartyDealFlow {
|
||||
logger.trace { "Recorded transaction." }
|
||||
|
||||
progressTracker.currentStep = COPYING_TO_REGULATOR
|
||||
val regulators = serviceHub.networkMapCache.regulatorNodes
|
||||
if (regulators.isNotEmpty()) {
|
||||
// Copy the transaction to every regulator in the network. This is obviously completely bogus, it's
|
||||
// just for demo purposes.
|
||||
regulators.forEach { send(it.serviceIdentities(ServiceType.regulator).first(), ftx) }
|
||||
}
|
||||
|
||||
// Copy the transaction to every regulator in the network. This is obviously completely bogus, it's
|
||||
// just for demo purposes.
|
||||
regulators.forEach { send(it, ftx) }
|
||||
|
||||
progressTracker.currentStep = COPYING_TO_COUNTERPARTY
|
||||
// Send the final transaction hash back to the other party.
|
||||
@ -173,8 +170,7 @@ object TwoPartyDealFlow {
|
||||
open class Instigator(override val otherParty: Party,
|
||||
override val payload: AutoOffer,
|
||||
override val progressTracker: ProgressTracker = Primary.tracker()) : Primary() {
|
||||
override val notaryNode: NodeInfo get() =
|
||||
serviceHub.networkMapCache.notaryNodes.single { it.notaryIdentity == payload.notary }
|
||||
override val notaryParty: Party get() = payload.notary
|
||||
|
||||
@Suspendable override fun checkProposal(stx: SignedTransaction) = requireThat {
|
||||
// Add some constraints here.
|
||||
|
@ -56,7 +56,6 @@ object TwoPartyTradeFlow {
|
||||
)
|
||||
|
||||
open class Seller(val otherParty: Party,
|
||||
val notaryNode: NodeInfo,
|
||||
val assetToSell: StateAndRef<OwnableState>,
|
||||
val price: Amount<Currency>,
|
||||
val myParty: PartyAndCertificate, // TODO Left because in tests it's used to pass anonymous party.
|
||||
|
@ -8,6 +8,7 @@ import net.corda.finance.`issued by`
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetwork.MockNode
|
||||
@ -31,10 +32,10 @@ class CashExitFlowTests {
|
||||
val nodes = mockNet.createSomeNodes(1)
|
||||
notaryNode = nodes.notaryNode
|
||||
bankOfCordaNode = nodes.partyNodes[0]
|
||||
notary = notaryNode.info.notaryIdentity
|
||||
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
|
||||
|
||||
mockNet.runNetwork()
|
||||
notary = bankOfCordaNode.services.getDefaultNotary()
|
||||
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture
|
||||
mockNet.runNetwork()
|
||||
future.getOrThrow()
|
||||
|
@ -8,6 +8,7 @@ import net.corda.finance.`issued by`
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetwork.MockNode
|
||||
@ -29,10 +30,10 @@ class CashIssueFlowTests {
|
||||
val nodes = mockNet.createSomeNodes(1)
|
||||
notaryNode = nodes.notaryNode
|
||||
bankOfCordaNode = nodes.partyNodes[0]
|
||||
notary = notaryNode.info.notaryIdentity
|
||||
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
|
||||
|
||||
mockNet.runNetwork()
|
||||
notary = bankOfCordaNode.services.getDefaultNotary()
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -13,6 +13,7 @@ import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.expect
|
||||
import net.corda.testing.expectEvents
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetwork.MockNode
|
||||
@ -36,11 +37,11 @@ class CashPaymentFlowTests {
|
||||
val nodes = mockNet.createSomeNodes(1)
|
||||
notaryNode = nodes.notaryNode
|
||||
bankOfCordaNode = nodes.partyNodes[0]
|
||||
notary = notaryNode.info.notaryIdentity
|
||||
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
|
||||
|
||||
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture
|
||||
mockNet.runNetwork()
|
||||
notary = bankOfCordaNode.services.getDefaultNotary()
|
||||
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture
|
||||
future.getOrThrow()
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package net.corda.core.node.services
|
||||
package net.corda.nodeapi
|
||||
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.serialization.CordaSerializable
|
@ -1,4 +1,4 @@
|
||||
package net.corda.core.node.services
|
||||
package net.corda.nodeapi
|
||||
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
|
||||
@ -27,15 +27,8 @@ class ServiceType private constructor(val id: String) {
|
||||
}
|
||||
|
||||
val notary: ServiceType = corda.getSubType("notary")
|
||||
val regulator: ServiceType = corda.getSubType("regulator")
|
||||
val networkMap: ServiceType = corda.getSubType("network_map")
|
||||
|
||||
@JvmStatic
|
||||
fun getServiceType(namespace: String, typeId: String): ServiceType {
|
||||
require(!namespace.startsWith("corda")) { "Corda namespace is protected" }
|
||||
return baseWithSubType(namespace, typeId)
|
||||
}
|
||||
|
||||
fun parse(id: String): ServiceType = ServiceType(id)
|
||||
|
||||
private fun baseWithSubType(baseId: String, subTypeId: String) = ServiceType("$baseId.$subTypeId")
|
||||
@ -45,8 +38,6 @@ class ServiceType private constructor(val id: String) {
|
||||
|
||||
fun isSubTypeOf(superType: ServiceType) = (id == superType.id) || id.startsWith(superType.id + ".")
|
||||
fun isNotary() = isSubTypeOf(notary)
|
||||
fun isValidatingNotary() = isNotary() && id.contains(".validating")
|
||||
fun isNetworkMap() = id == networkMap.id
|
||||
|
||||
override fun equals(other: Any?): Boolean = other === this || other is ServiceType && other.id == this.id
|
||||
override fun hashCode(): Int = id.hashCode()
|
@ -5,12 +5,12 @@ import net.corda.core.internal.div
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.node.internal.NodeStartup
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.nodeapi.ServiceType
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.driver.ListenProcessDeathException
|
||||
import net.corda.testing.driver.NetworkMapStartStrategy
|
||||
@ -18,6 +18,7 @@ import net.corda.testing.ProjectStructure.projectRootDir
|
||||
import net.corda.testing.driver.driver
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import java.io.*
|
||||
import java.nio.file.Files
|
||||
@ -54,9 +55,10 @@ class BootTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore("Need rewriting to produce too big network map registration (adverticed services trick doesn't work after services removal).")
|
||||
@Test
|
||||
fun `node quits on failure to register with network map`() {
|
||||
val tooManyAdvertisedServices = (1..100).map { ServiceInfo(ServiceType.regulator.getSubType("$it")) }.toSet()
|
||||
val tooManyAdvertisedServices = (1..100).map { ServiceInfo(ServiceType.notary.getSubType("$it")) }.toSet()
|
||||
driver(networkMapStartStrategy = NetworkMapStartStrategy.Nominated(ALICE.name)) {
|
||||
val future = startNode(providedName = ALICE.name, advertisedServices = tooManyAdvertisedServices)
|
||||
assertFailsWith(ListenProcessDeathException::class) { future.getOrThrow() }
|
||||
|
@ -6,13 +6,13 @@ import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.internal.concurrent.transpose
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.minutes
|
||||
import net.corda.finance.DOLLARS
|
||||
import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.chooseIdentity
|
||||
@ -110,9 +110,10 @@ class NodePerformanceTests {
|
||||
a as NodeHandle.InProcess
|
||||
val metricRegistry = startReporter(shutdownManager, a.node.services.monitoringService.metrics)
|
||||
a.rpcClientToNode().use("A", "A") { connection ->
|
||||
val notary = connection.proxy.notaryIdentities().first().party
|
||||
println("ISSUING")
|
||||
val doneFutures = (1..100).toList().parallelStream().map {
|
||||
connection.proxy.startFlow(::CashIssueFlow, 1.DOLLARS, OpaqueBytes.of(0), a.nodeInfo.notaryIdentity).returnValue
|
||||
connection.proxy.startFlow(::CashIssueFlow, 1.DOLLARS, OpaqueBytes.of(0), notary).returnValue
|
||||
}.toList()
|
||||
doneFutures.transpose().get()
|
||||
println("STARTING PAYMENT")
|
||||
|
@ -1,42 +0,0 @@
|
||||
package net.corda.node.services
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.driver.driver
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class AdvertisedServiceTests {
|
||||
private val serviceName = CordaX500Name(organisation = "Custom Service", locality = "London", country = "GB")
|
||||
private val serviceType = ServiceType.corda.getSubType("custom")
|
||||
private val user = "bankA"
|
||||
private val pass = "passA"
|
||||
|
||||
|
||||
@StartableByRPC
|
||||
class ServiceTypeCheckingFlow : FlowLogic<Boolean>() {
|
||||
@Suspendable
|
||||
override fun call(): Boolean {
|
||||
return serviceHub.networkMapCache.getAnyServiceOfType(ServiceType.corda.getSubType("custom")) != null
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `service is accessible through getAnyServiceOfType`() {
|
||||
driver(startNodesInProcess = true) {
|
||||
val bankA = startNode(rpcUsers = listOf(User(user, pass, setOf(startFlowPermission<ServiceTypeCheckingFlow>())))).get()
|
||||
startNode(providedName = serviceName, advertisedServices = setOf(ServiceInfo(serviceType))).get()
|
||||
bankA.rpcClientToNode().use(user, pass) { connection ->
|
||||
val result = connection.proxy.startFlow(::ServiceTypeCheckingFlow).returnValue.get()
|
||||
assertTrue(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,6 @@ import net.corda.core.flows.NotaryFlow
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
@ -23,10 +22,12 @@ import net.corda.node.services.transactions.BFTNonValidatingNotaryService
|
||||
import net.corda.node.services.transactions.minClusterSize
|
||||
import net.corda.node.services.transactions.minCorrectReplicas
|
||||
import net.corda.node.utilities.ServiceIdentityGenerator
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Test
|
||||
@ -47,7 +48,7 @@ class BFTNotaryServiceTests {
|
||||
mockNet.stopNodes()
|
||||
}
|
||||
|
||||
private fun bftNotaryCluster(clusterSize: Int, exposeRaces: Boolean = false): Party {
|
||||
private fun bftNotaryCluster(clusterSize: Int, exposeRaces: Boolean = false) {
|
||||
Files.deleteIfExists("config" / "currentView") // XXX: Make config object warn if this exists?
|
||||
val replicaIds = (0 until clusterSize)
|
||||
val party = ServiceIdentityGenerator.generateToDisk(
|
||||
@ -66,13 +67,14 @@ class BFTNotaryServiceTests {
|
||||
whenever(it.notaryClusterAddresses).thenReturn(notaryClusterAddresses)
|
||||
})
|
||||
}
|
||||
return party
|
||||
mockNet.runNetwork() // Exchange initial network map registration messages.
|
||||
}
|
||||
|
||||
/** Failure mode is the redundant replica gets stuck in startup, so we can't dispose it cleanly at the end. */
|
||||
@Test
|
||||
fun `all replicas start even if there is a new consensus during startup`() {
|
||||
val notary = bftNotaryCluster(minClusterSize(1), true) // This true adds a sleep to expose the race.
|
||||
bftNotaryCluster(minClusterSize(1), true) // This true adds a sleep to expose the race.
|
||||
val notary = node.services.getDefaultNotary()
|
||||
val f = node.run {
|
||||
val trivialTx = signInitialTransaction(notary) {
|
||||
addOutputState(DummyContract.SingleOwnerState(owner = info.chooseIdentity()), DUMMY_PROGRAM_ID)
|
||||
@ -96,7 +98,8 @@ class BFTNotaryServiceTests {
|
||||
|
||||
private fun detectDoubleSpend(faultyReplicas: Int) {
|
||||
val clusterSize = minClusterSize(faultyReplicas)
|
||||
val notary = bftNotaryCluster(clusterSize)
|
||||
bftNotaryCluster(clusterSize)
|
||||
val notary = node.services.getDefaultNotary()
|
||||
node.run {
|
||||
val issueTx = signInitialTransaction(notary) {
|
||||
addOutputState(DummyContract.SingleOwnerState(owner = info.chooseIdentity()), DUMMY_PROGRAM_ID)
|
||||
|
@ -2,7 +2,6 @@ package net.corda.node.services
|
||||
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.internal.bufferUntilSubscribed
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.messaging.StateMachineUpdate
|
||||
@ -51,14 +50,9 @@ class DistributedServiceTests : DriverBasedTest() {
|
||||
raftNotaryIdentity = notaryIdentity
|
||||
notaries = notaryNodes.map { it as NodeHandle.OutOfProcess }
|
||||
|
||||
val notariesIdentities = notaries.fold(HashSet<PartyAndCertificate>()) {
|
||||
acc, elem -> acc.addAll(elem.nodeInfo.legalIdentitiesAndCerts)
|
||||
acc
|
||||
}
|
||||
assertEquals(notaries.size, clusterSize)
|
||||
// Check that each notary has different identity as a node.
|
||||
assertEquals(notaries.size, notariesIdentities.size - notaries[0].nodeInfo.advertisedServices.size)
|
||||
|
||||
assertEquals(notaries.size, notaries.map { it.nodeInfo.chooseIdentity() }.toSet().size)
|
||||
// Connect to Alice and the notaries
|
||||
fun connectRpc(node: NodeHandle): CordaRPCOps {
|
||||
val client = node.rpcClientToNode()
|
||||
|
@ -8,7 +8,6 @@ import net.corda.core.internal.elapsedTime
|
||||
import net.corda.core.internal.times
|
||||
import net.corda.core.messaging.MessageRecipients
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
@ -19,6 +18,7 @@ import net.corda.node.services.messaging.*
|
||||
import net.corda.node.services.transactions.RaftValidatingNotaryService
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.node.utilities.ServiceIdentityGenerator
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.node.NodeBasedTest
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
@ -84,7 +84,8 @@ class P2PMessagingTest : NodeBasedTest() {
|
||||
startNode(ALICE.name)
|
||||
).transpose().getOrThrow()
|
||||
|
||||
assertAllNodesAreUsed(listOf(networkMapNode, serviceNode2), SERVICE_2_NAME.copy(commonName = "DistributedService"), alice)
|
||||
val serviceName = serviceNode2.info.legalIdentities[1].name
|
||||
assertAllNodesAreUsed(listOf(networkMapNode, serviceNode2), serviceName, alice)
|
||||
}
|
||||
|
||||
@Ignore
|
||||
|
@ -8,7 +8,6 @@ import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.schemas.MappedSchema
|
||||
import net.corda.core.schemas.PersistentState
|
||||
import net.corda.core.schemas.QueryableState
|
||||
@ -19,6 +18,7 @@ import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.services.FlowPermissions
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
|
@ -22,7 +22,6 @@ import net.corda.core.messaging.RPCOps
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.node.CordaPluginRegistry
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.ServiceEntry
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.node.services.*
|
||||
import net.corda.core.node.services.NetworkMapCache.MapChange
|
||||
@ -37,6 +36,8 @@ import net.corda.node.internal.cordapp.CordappLoader
|
||||
import net.corda.node.internal.cordapp.CordappProvider
|
||||
import net.corda.node.services.NotaryChangeHandler
|
||||
import net.corda.node.services.NotifyTransactionHandler
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.nodeapi.ServiceType
|
||||
import net.corda.node.services.api.*
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.config.configureWithDevSSLCertificate
|
||||
@ -75,6 +76,7 @@ import java.lang.reflect.InvocationTargetException
|
||||
import java.nio.file.Path
|
||||
import java.security.KeyPair
|
||||
import java.security.KeyStoreException
|
||||
import java.security.PublicKey
|
||||
import java.security.cert.CertificateFactory
|
||||
import java.security.cert.X509Certificate
|
||||
import java.sql.Connection
|
||||
@ -134,8 +136,9 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
|
||||
protected val services: ServiceHubInternal get() = _services
|
||||
private lateinit var _services: ServiceHubInternalImpl
|
||||
lateinit var legalIdentity: PartyAndCertificate
|
||||
protected lateinit var legalIdentity: PartyAndCertificate
|
||||
protected lateinit var info: NodeInfo
|
||||
protected var myNotaryIdentity: PartyAndCertificate? = null
|
||||
protected lateinit var checkpointStorage: CheckpointStorage
|
||||
protected lateinit var smm: StateMachineManager
|
||||
protected lateinit var attachments: NodeAttachmentService
|
||||
@ -391,7 +394,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
services.auditService, services.monitoringService, services.networkMapCache, services.schemaService,
|
||||
services.transactionVerifierService, services.validatedTransactions, services.contractUpgradeService,
|
||||
services, this)
|
||||
makeAdvertisedServices(tokenizableServices)
|
||||
makeNetworkServices(tokenizableServices)
|
||||
return tokenizableServices
|
||||
}
|
||||
|
||||
@ -414,22 +417,21 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
}
|
||||
|
||||
private fun makeInfo(legalIdentity: PartyAndCertificate): NodeInfo {
|
||||
val advertisedServiceEntries = makeServiceEntries()
|
||||
// TODO We keep only notary identity as additional legalIdentity if we run it on a node . Multiple identities need more design thinking.
|
||||
myNotaryIdentity = getNotaryIdentity()
|
||||
val allIdentitiesList = mutableListOf(legalIdentity)
|
||||
allIdentitiesList.addAll(advertisedServiceEntries.map { it.identity }) // TODO Will we keep service identities here, for example notaries?
|
||||
myNotaryIdentity?.let { allIdentitiesList.add(it) }
|
||||
val addresses = myAddresses() // TODO There is no support for multiple IP addresses yet.
|
||||
return NodeInfo(addresses, allIdentitiesList, platformVersion, advertisedServiceEntries, platformClock.instant().toEpochMilli())
|
||||
return NodeInfo(addresses, allIdentitiesList, platformVersion, platformClock.instant().toEpochMilli())
|
||||
}
|
||||
|
||||
/**
|
||||
* A service entry contains the advertised [ServiceInfo] along with the service identity. The identity *name* is
|
||||
* taken from the configuration or, if non specified, generated by combining the node's legal name and the service id.
|
||||
* Used only for notary identities.
|
||||
*/
|
||||
protected open fun makeServiceEntries(): List<ServiceEntry> {
|
||||
return advertisedServices.map {
|
||||
val identity = obtainIdentity(it)
|
||||
ServiceEntry(it, identity)
|
||||
}
|
||||
protected open fun getNotaryIdentity(): PartyAndCertificate? {
|
||||
return advertisedServices.singleOrNull { it.type.isNotary() }?.let { obtainIdentity(it) }
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@ -478,8 +480,8 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
}
|
||||
}
|
||||
|
||||
private fun makeAdvertisedServices(tokenizableServices: MutableList<Any>) {
|
||||
val serviceTypes = info.advertisedServices.map { it.info.type }
|
||||
private fun makeNetworkServices(tokenizableServices: MutableList<Any>) {
|
||||
val serviceTypes = advertisedServices.map { it.type }
|
||||
inNodeNetworkMapService = if (NetworkMapService.type in serviceTypes) makeNetworkMapService() else NullNetworkMapService
|
||||
val notaryServiceType = serviceTypes.singleOrNull { it.isNotary() }
|
||||
if (notaryServiceType != null) {
|
||||
@ -584,7 +586,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
.filterNotNull()
|
||||
.toTypedArray()
|
||||
val service = PersistentIdentityService(info.legalIdentitiesAndCerts, trustRoot = trustRoot, caCertificates = *caCertificates)
|
||||
services.networkMapCache.partyNodes.forEach { it.legalIdentitiesAndCerts.forEach { service.verifyAndRegisterIdentity(it) } }
|
||||
services.networkMapCache.allNodes.forEach { it.legalIdentitiesAndCerts.forEach { service.verifyAndRegisterIdentity(it) } }
|
||||
services.networkMapCache.changed.subscribe { mapChange ->
|
||||
// TODO how should we handle network map removal
|
||||
if (mapChange is MapChange.Added) {
|
||||
@ -628,7 +630,12 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
// Create node identity if service info = null
|
||||
Pair("identity", myLegalName.copy(commonName = null))
|
||||
} else {
|
||||
val name = serviceInfo.name ?: myLegalName.copy(commonName = serviceInfo.type.id)
|
||||
// Ensure that we always have notary in name and type of it. TODO It is temporary solution until we will have proper handling of NetworkParameters
|
||||
val baseName = serviceInfo.name ?: myLegalName
|
||||
val name = if (baseName.commonName == null)
|
||||
baseName.copy(commonName = serviceInfo.type.id)
|
||||
else
|
||||
baseName.copy(commonName = baseName.commonName + " " + serviceInfo.type.id)
|
||||
Pair(serviceInfo.type.id, name)
|
||||
}
|
||||
|
||||
@ -728,6 +735,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
override val myInfo: NodeInfo get() = info
|
||||
override val database: CordaPersistence get() = this@AbstractNode.database
|
||||
override val configuration: NodeConfiguration get() = this@AbstractNode.configuration
|
||||
override val notaryIdentityKey: PublicKey get() = myNotaryIdentity?.owningKey ?: throw IllegalArgumentException("Node doesn't have notary identity key")
|
||||
|
||||
override fun <T : SerializeAsToken> cordaService(type: Class<T>): T {
|
||||
require(type.isAnnotationPresent(CordaService::class.java)) { "${type.name} is not a Corda service" }
|
||||
|
@ -10,6 +10,7 @@ import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.messaging.*
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.NetworkMapCache
|
||||
@ -114,6 +115,10 @@ class CordaRPCOpsImpl(
|
||||
return services.myInfo
|
||||
}
|
||||
|
||||
override fun notaryIdentities(): List<PartyAndCertificate> {
|
||||
return services.networkMapCache.notaryIdentities
|
||||
}
|
||||
|
||||
override fun addVaultTransactionNote(txnId: SecureHash, txnNote: String) {
|
||||
return database.transaction {
|
||||
services.vaultService.addNoteToTransaction(txnId, txnNote)
|
||||
@ -202,7 +207,7 @@ class CordaRPCOpsImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun nodeIdentityFromParty(party: AbstractParty): NodeInfo? {
|
||||
override fun nodeInfoFromParty(party: AbstractParty): NodeInfo? {
|
||||
return database.transaction {
|
||||
services.networkMapCache.getNodeByLegalIdentity(party)
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import net.corda.core.internal.concurrent.thenMatch
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.messaging.RPCOps
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.serialization.SerializationDefaults
|
||||
import net.corda.core.utilities.*
|
||||
import net.corda.node.VersionInfo
|
||||
@ -19,6 +18,7 @@ import net.corda.node.serialization.KryoServerSerializationScheme
|
||||
import net.corda.node.serialization.NodeClock
|
||||
import net.corda.node.services.RPCUserService
|
||||
import net.corda.node.services.RPCUserServiceImpl
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.config.FullNodeConfiguration
|
||||
import net.corda.node.services.messaging.ArtemisMessagingServer
|
||||
import net.corda.node.services.messaging.ArtemisMessagingServer.Companion.ipDetectRequestProperty
|
||||
|
@ -5,9 +5,9 @@ import com.typesafe.config.ConfigException
|
||||
import joptsimple.OptionException
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.internal.concurrent.thenMatch
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.node.*
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.config.FullNodeConfiguration
|
||||
import net.corda.node.services.transactions.bftSMaRtSerialFilter
|
||||
import net.corda.node.shell.InteractiveShell
|
||||
|
@ -8,13 +8,10 @@ import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.InitiatedBy
|
||||
import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.CordaPluginRegistry
|
||||
import net.corda.core.node.services.CordaService
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.schemas.MappedSchema
|
||||
import net.corda.core.serialization.SerializeAsToken
|
||||
import net.corda.core.utilities.debug
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.node.internal.classloading.requireAnnotation
|
||||
import java.lang.reflect.Modifier
|
||||
@ -23,9 +20,7 @@ import java.net.URI
|
||||
import java.net.URL
|
||||
import java.net.URLClassLoader
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
import java.util.stream.Collectors
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.streams.toList
|
||||
|
||||
|
@ -38,7 +38,7 @@ class NotaryChangeHandler(otherSide: Party) : AbstractStateReplacementFlow.Accep
|
||||
}
|
||||
|
||||
// TODO: load and compare against notary whitelist from config. Remove the check below
|
||||
val isNotary = serviceHub.networkMapCache.notaryNodes.any { it.notaryIdentity == newNotary }
|
||||
val isNotary = serviceHub.networkMapCache.isNotary(newNotary)
|
||||
if (!isNotary) {
|
||||
throw StateReplacementException("The proposed node $newNotary does not run a Notary service")
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
package net.corda.node.services.api
|
||||
|
||||
import net.corda.core.node.services.ServiceType
|
||||
|
||||
/**
|
||||
* Placeholder interface for regulator services.
|
||||
*/
|
||||
interface RegulatorService {
|
||||
companion object {
|
||||
val type = ServiceType.regulator
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
package net.corda.node.services.config
|
||||
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.node.internal.NetworkMapInfo
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.messaging.CertificateChainCheckPolicy
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.nodeapi.User
|
||||
|
@ -12,17 +12,16 @@ import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.KeyManagementService
|
||||
import net.corda.core.node.services.NetworkMapCache
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.core.utilities.debug
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.nodeapi.ServiceType
|
||||
import net.corda.node.services.api.AbstractNodeService
|
||||
import net.corda.node.services.api.ServiceHubInternal
|
||||
import net.corda.node.services.messaging.MessageHandlerRegistration
|
||||
import net.corda.node.services.messaging.MessagingService
|
||||
import net.corda.node.services.messaging.ServiceRequestMessage
|
||||
import net.corda.node.services.messaging.createMessage
|
||||
import net.corda.node.services.network.NetworkMapService.*
|
||||
|
@ -4,6 +4,7 @@ import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import net.corda.core.internal.bufferUntilSubscribed
|
||||
import net.corda.core.internal.concurrent.map
|
||||
@ -58,8 +59,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
// TODO Small explanation, partyNodes and registeredNodes is left in memory as it was before, because it will be removed in
|
||||
// next PR that gets rid of services. These maps are used only for queries by service.
|
||||
protected val registeredNodes: MutableMap<PublicKey, NodeInfo> = Collections.synchronizedMap(HashMap())
|
||||
override val partyNodes: MutableList<NodeInfo> get() = registeredNodes.map { it.value }.toMutableList()
|
||||
override val networkMapNodes: List<NodeInfo> get() = getNodesWithService(NetworkMapService.type)
|
||||
protected val partyNodes: MutableList<NodeInfo> get() = registeredNodes.map { it.value }.toMutableList()
|
||||
private val _changed = PublishSubject.create<MapChange>()
|
||||
// We use assignment here so that multiple subscribers share the same wrapped Observable.
|
||||
override val changed: Observable<MapChange> = _changed.wrapWithDatabaseTransaction()
|
||||
@ -69,6 +69,15 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
override val nodeReady: CordaFuture<Void?> get() = _registrationFuture
|
||||
private var _loadDBSuccess: Boolean = false
|
||||
override val loadDBSuccess get() = _loadDBSuccess
|
||||
// TODO From the NetworkMapService redesign doc: Remove the concept of network services.
|
||||
// As a temporary hack, just assume for now that every network has a notary service named "Notary Service" that can be looked up in the map.
|
||||
// This should eliminate the only required usage of services.
|
||||
// It is ensured on node startup when constructing a notary that the name contains "notary".
|
||||
override val notaryIdentities: List<PartyAndCertificate> get() {
|
||||
return partyNodes.flatMap { it.legalIdentitiesAndCerts }.filter {
|
||||
it.name.toString().contains("corda.notary", true)
|
||||
}.distinct().sortedBy { it.name.toString() } // Distinct, because of distributed service nodes.
|
||||
}
|
||||
|
||||
init {
|
||||
serviceHub.database.transaction { loadFromDB() }
|
||||
@ -80,8 +89,8 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
return PartyInfo.SingleNode(party, nodes[0].addresses)
|
||||
}
|
||||
for (node in nodes) {
|
||||
for (service in node.advertisedServices) {
|
||||
if (service.identity.party == party) {
|
||||
for (identity in node.legalIdentities) {
|
||||
if (identity == party) {
|
||||
return PartyInfo.DistributedNode(party)
|
||||
}
|
||||
}
|
||||
@ -89,9 +98,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
return null
|
||||
}
|
||||
|
||||
// TODO See comment to queryByLegalName why it's left like that.
|
||||
override fun getNodeByLegalName(principal: CordaX500Name): NodeInfo? = partyNodes.singleOrNull { principal in it.legalIdentities.map { it.name } }
|
||||
//serviceHub!!.database.transaction { queryByLegalName(principal).firstOrNull() }
|
||||
override fun getNodeByLegalName(name: CordaX500Name): NodeInfo? = serviceHub.database.transaction { queryByLegalName(name).firstOrNull() }
|
||||
override fun getNodesByLegalIdentityKey(identityKey: PublicKey): List<NodeInfo> =
|
||||
serviceHub.database.transaction { queryByIdentityKey(identityKey) }
|
||||
override fun getNodeByLegalIdentity(party: AbstractParty): NodeInfo? {
|
||||
@ -194,6 +201,12 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
}
|
||||
}
|
||||
|
||||
override val allNodes: List<NodeInfo> get () = serviceHub.database.transaction {
|
||||
createSession {
|
||||
getAllInfos(it).map { it.toNodeInfo() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun processRegistration(reg: NodeRegistration) {
|
||||
// TODO: Implement filtering by sequence number, so we only accept changes that are
|
||||
// more recent than the latest change we've processed.
|
||||
@ -251,8 +264,8 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
// network map registration on network map node)
|
||||
serviceHub.database.dataSource.connection.use {
|
||||
val session = serviceHub.database.entityManagerFactory.withOptions().connection(it.apply {
|
||||
transactionIsolation = 1
|
||||
}).openSession()
|
||||
transactionIsolation = 1
|
||||
}).openSession()
|
||||
session.use {
|
||||
val tx = session.beginTransaction()
|
||||
// TODO For now the main legal identity is left in NodeInfo, this should be set comparision/come up with index for NodeInfo?
|
||||
@ -322,7 +335,6 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
legalIdentitiesAndCerts = nodeInfo.legalIdentitiesAndCerts.mapIndexed { idx, elem ->
|
||||
NodeInfoSchemaV1.DBPartyAndCertificate(elem, isMain = idx == 0) },
|
||||
platformVersion = nodeInfo.platformVersion,
|
||||
advertisedServices = nodeInfo.advertisedServices.map { NodeInfoSchemaV1.DBServiceEntry(it.serialize().bytes) },
|
||||
serial = nodeInfo.serial
|
||||
)
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ package net.corda.node.services.transactions
|
||||
|
||||
import net.corda.core.flows.NotaryFlow
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.node.services.TimeWindowChecker
|
||||
import net.corda.core.node.services.TrustedAuthorityNotaryService
|
||||
import net.corda.nodeapi.ServiceType
|
||||
import net.corda.node.services.api.ServiceHubInternal
|
||||
|
||||
/** A simple Notary service that does not perform transaction validation */
|
||||
|
@ -38,7 +38,7 @@ class ValidatingNotaryFlow(otherSide: Party, service: TrustedAuthorityNotaryServ
|
||||
|
||||
private fun checkSignatures(stx: SignedTransaction) {
|
||||
try {
|
||||
stx.verifySignaturesExcept(serviceHub.myInfo.notaryIdentity.owningKey)
|
||||
stx.verifySignaturesExcept(serviceHub.notaryIdentityKey)
|
||||
} catch(e: SignatureException) {
|
||||
throw NotaryException(NotaryError.TransactionInvalid(e))
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ package net.corda.node.services.transactions
|
||||
|
||||
import net.corda.core.flows.NotaryFlow
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.node.services.TimeWindowChecker
|
||||
import net.corda.core.node.services.TrustedAuthorityNotaryService
|
||||
import net.corda.nodeapi.ServiceType
|
||||
import net.corda.node.services.api.ServiceHubInternal
|
||||
|
||||
/** A Notary service that validates the transaction chain of the submitted transaction before committing it */
|
||||
|
@ -9,8 +9,8 @@ import net.corda.core.crypto.keys
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.flows.StateMachineRunId
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.messaging.*
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.Vault
|
||||
import net.corda.core.node.services.queryBy
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
@ -28,6 +28,7 @@ import net.corda.node.services.messaging.CURRENT_RPC_CONTEXT
|
||||
import net.corda.node.services.messaging.RpcContext
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.PermissionException
|
||||
import net.corda.nodeapi.User
|
||||
@ -59,6 +60,7 @@ class CordaRPCOpsImplTest {
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var aliceNode: StartedNode<MockNode>
|
||||
lateinit var notaryNode: StartedNode<MockNode>
|
||||
lateinit var notary: Party
|
||||
lateinit var rpc: CordaRPCOps
|
||||
lateinit var stateMachineUpdates: Observable<StateMachineUpdate>
|
||||
lateinit var transactions: Observable<SignedTransaction>
|
||||
@ -78,6 +80,7 @@ class CordaRPCOpsImplTest {
|
||||
|
||||
mockNet.runNetwork()
|
||||
networkMap.internals.ensureRegistered()
|
||||
notary = rpc.notaryIdentities().first().party
|
||||
}
|
||||
|
||||
@After
|
||||
@ -102,7 +105,7 @@ class CordaRPCOpsImplTest {
|
||||
|
||||
// Tell the monitoring service node to issue some cash
|
||||
val recipient = aliceNode.info.chooseIdentity()
|
||||
val result = rpc.startFlow(::CashIssueFlow, Amount(quantity, GBP), ref, notaryNode.info.notaryIdentity)
|
||||
val result = rpc.startFlow(::CashIssueFlow, Amount(quantity, GBP), ref, notary)
|
||||
mockNet.runNetwork()
|
||||
|
||||
var issueSmId: StateMachineRunId? = null
|
||||
@ -146,7 +149,7 @@ class CordaRPCOpsImplTest {
|
||||
val result = rpc.startFlow(::CashIssueFlow,
|
||||
100.DOLLARS,
|
||||
OpaqueBytes(ByteArray(1, { 1 })),
|
||||
notaryNode.info.notaryIdentity
|
||||
notary
|
||||
)
|
||||
|
||||
mockNet.runNetwork()
|
||||
@ -196,7 +199,7 @@ class CordaRPCOpsImplTest {
|
||||
val signaturePubKeys = stx.sigs.map { it.by }.toSet()
|
||||
// Alice and Notary signed
|
||||
require(aliceNode.services.keyManagementService.filterMyKeys(signaturePubKeys).toList().isNotEmpty())
|
||||
require(notaryNode.info.notaryIdentity.owningKey.isFulfilledBy(signaturePubKeys))
|
||||
require(notary.owningKey.isFulfilledBy(signaturePubKeys))
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -221,7 +224,7 @@ class CordaRPCOpsImplTest {
|
||||
fun `cash command by user not permissioned for cash`() {
|
||||
CURRENT_RPC_CONTEXT.set(RpcContext(User("user", "pwd", permissions = emptySet())))
|
||||
assertThatExceptionOfType(PermissionException::class.java).isThrownBy {
|
||||
rpc.startFlow(::CashIssueFlow, Amount(100, USD), OpaqueBytes(ByteArray(1, { 1 })), notaryNode.info.notaryIdentity)
|
||||
rpc.startFlow(::CashIssueFlow, Amount(100, USD), OpaqueBytes(ByteArray(1, { 1 })), notary)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
package net.corda.node.messaging
|
||||
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.messaging.Message
|
||||
import net.corda.node.services.messaging.TopicStringValidator
|
||||
import net.corda.node.services.messaging.createMessage
|
||||
|
@ -18,8 +18,6 @@ import net.corda.core.internal.rootCause
|
||||
import net.corda.core.messaging.DataFeed
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.messaging.StateMachineTransactionMapping
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.Vault
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
@ -38,6 +36,7 @@ import net.corda.finance.contracts.asset.*
|
||||
import net.corda.finance.flows.TwoPartyTradeFlow.Buyer
|
||||
import net.corda.finance.flows.TwoPartyTradeFlow.Seller
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.api.WritableTransactionStorage
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.persistence.DBTransactionStorage
|
||||
@ -99,23 +98,25 @@ class TwoPartyTradeFlowTests {
|
||||
val bankNode = basketOfNodes.partyNodes[2]
|
||||
val cashIssuer = bankNode.info.chooseIdentity().ref(1)
|
||||
val cpIssuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
|
||||
val notary = aliceNode.services.getDefaultNotary()
|
||||
|
||||
|
||||
aliceNode.internals.disableDBCloseOnStop()
|
||||
bobNode.internals.disableDBCloseOnStop()
|
||||
|
||||
bobNode.database.transaction {
|
||||
bobNode.services.fillWithSomeTestCash(2000.DOLLARS, bankNode.services, outputNotary = notaryNode.info.notaryIdentity,
|
||||
bobNode.services.fillWithSomeTestCash(2000.DOLLARS, bankNode.services, outputNotary = notary,
|
||||
issuedBy = cashIssuer)
|
||||
}
|
||||
|
||||
val alicesFakePaper = aliceNode.database.transaction {
|
||||
fillUpForSeller(false, cpIssuer, aliceNode.info.chooseIdentity(),
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notaryNode.info.notaryIdentity).second
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notary).second
|
||||
}
|
||||
|
||||
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
|
||||
|
||||
val (bobStateMachine, aliceResult) = runBuyerAndSeller(notaryNode, aliceNode, bobNode,
|
||||
val (bobStateMachine, aliceResult) = runBuyerAndSeller(notary, aliceNode, bobNode,
|
||||
"alice's paper".outputStateAndRef())
|
||||
|
||||
// TODO: Verify that the result was inserted into the transaction database.
|
||||
@ -146,18 +147,19 @@ class TwoPartyTradeFlowTests {
|
||||
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
|
||||
val issuer = bankNode.info.chooseIdentity().ref(1)
|
||||
val notary = aliceNode.services.getDefaultNotary()
|
||||
|
||||
aliceNode.internals.disableDBCloseOnStop()
|
||||
bobNode.internals.disableDBCloseOnStop()
|
||||
|
||||
val cashStates = bobNode.database.transaction {
|
||||
bobNode.services.fillWithSomeTestCash(2000.DOLLARS, bankNode.services, notaryNode.info.notaryIdentity, 3, 3,
|
||||
bobNode.services.fillWithSomeTestCash(2000.DOLLARS, bankNode.services, notary, 3, 3,
|
||||
issuedBy = issuer)
|
||||
}
|
||||
|
||||
val alicesFakePaper = aliceNode.database.transaction {
|
||||
fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notaryNode.info.notaryIdentity).second
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notary).second
|
||||
}
|
||||
|
||||
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
|
||||
@ -171,7 +173,7 @@ class TwoPartyTradeFlowTests {
|
||||
}
|
||||
}
|
||||
|
||||
val (bobStateMachine, aliceResult) = runBuyerAndSeller(notaryNode, aliceNode, bobNode,
|
||||
val (bobStateMachine, aliceResult) = runBuyerAndSeller(notary, aliceNode, bobNode,
|
||||
"alice's paper".outputStateAndRef())
|
||||
|
||||
assertEquals(aliceResult.getOrThrow(), bobStateMachine.getOrThrow().resultFuture.getOrThrow())
|
||||
@ -216,17 +218,18 @@ class TwoPartyTradeFlowTests {
|
||||
val networkMapAddress = notaryNode.network.myAddress
|
||||
|
||||
mockNet.runNetwork() // Clear network map registration messages
|
||||
val notary = aliceNode.services.getDefaultNotary()
|
||||
|
||||
bobNode.database.transaction {
|
||||
bobNode.services.fillWithSomeTestCash(2000.DOLLARS, bankNode.services, outputNotary = notaryNode.info.notaryIdentity,
|
||||
bobNode.services.fillWithSomeTestCash(2000.DOLLARS, bankNode.services, outputNotary = notary,
|
||||
issuedBy = issuer)
|
||||
}
|
||||
val alicesFakePaper = aliceNode.database.transaction {
|
||||
fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notaryNode.info.notaryIdentity).second
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notary).second
|
||||
}
|
||||
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
|
||||
val aliceFuture = runBuyerAndSeller(notaryNode, aliceNode, bobNode, "alice's paper".outputStateAndRef()).sellerResult
|
||||
val aliceFuture = runBuyerAndSeller(notary, aliceNode, bobNode, "alice's paper".outputStateAndRef()).sellerResult
|
||||
|
||||
// Everything is on this thread so we can now step through the flow one step at a time.
|
||||
// Seller Alice already sent a message to Buyer Bob. Pump once:
|
||||
@ -332,9 +335,9 @@ class TwoPartyTradeFlowTests {
|
||||
val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
|
||||
val bankNode = makeNodeWithTracking(notaryNode.network.myAddress, BOC.name)
|
||||
val issuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
|
||||
|
||||
mockNet.runNetwork()
|
||||
notaryNode.internals.ensureRegistered()
|
||||
val notary = aliceNode.services.getDefaultNotary()
|
||||
|
||||
mockNet.registerIdentities()
|
||||
|
||||
@ -352,17 +355,17 @@ class TwoPartyTradeFlowTests {
|
||||
}
|
||||
|
||||
val bobsFakeCash = fillUpForBuyer(false, issuer, AnonymousParty(bobNode.info.chooseIdentity().owningKey),
|
||||
notaryNode.info.notaryIdentity).second
|
||||
notary).second
|
||||
val bobsSignedTxns = insertFakeTransactions(bobsFakeCash, bobNode, notaryNode, bankNode)
|
||||
val alicesFakePaper = aliceNode.database.transaction {
|
||||
fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), attachmentID, notaryNode.info.notaryIdentity).second
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), attachmentID, notary).second
|
||||
}
|
||||
val alicesSignedTxns = insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
|
||||
|
||||
mockNet.runNetwork() // Clear network map registration messages
|
||||
|
||||
runBuyerAndSeller(notaryNode, aliceNode, bobNode, "alice's paper".outputStateAndRef())
|
||||
runBuyerAndSeller(notary, aliceNode, bobNode, "alice's paper".outputStateAndRef())
|
||||
|
||||
mockNet.runNetwork()
|
||||
|
||||
@ -441,6 +444,7 @@ class TwoPartyTradeFlowTests {
|
||||
|
||||
mockNet.runNetwork()
|
||||
notaryNode.internals.ensureRegistered()
|
||||
val notary = aliceNode.services.getDefaultNotary()
|
||||
|
||||
mockNet.registerIdentities()
|
||||
|
||||
@ -458,12 +462,12 @@ class TwoPartyTradeFlowTests {
|
||||
|
||||
val bobsKey = bobNode.services.keyManagementService.keys.single()
|
||||
val bobsFakeCash = fillUpForBuyer(false, issuer, AnonymousParty(bobsKey),
|
||||
notaryNode.info.notaryIdentity).second
|
||||
notary).second
|
||||
insertFakeTransactions(bobsFakeCash, bobNode, notaryNode, bankNode)
|
||||
|
||||
val alicesFakePaper = aliceNode.database.transaction {
|
||||
fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), attachmentID, notaryNode.info.notaryIdentity).second
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), attachmentID, notary).second
|
||||
}
|
||||
|
||||
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
|
||||
@ -474,7 +478,7 @@ class TwoPartyTradeFlowTests {
|
||||
val aliceTxMappings = with(aliceNode) {
|
||||
database.transaction { services.stateMachineRecordedTransactionMapping.track().updates }
|
||||
}
|
||||
val aliceSmId = runBuyerAndSeller(notaryNode, aliceNode, bobNode,
|
||||
val aliceSmId = runBuyerAndSeller(notary, aliceNode, bobNode,
|
||||
"alice's paper".outputStateAndRef()).sellerId
|
||||
|
||||
mockNet.runNetwork()
|
||||
@ -533,21 +537,21 @@ class TwoPartyTradeFlowTests {
|
||||
val sellerId: StateMachineRunId
|
||||
)
|
||||
|
||||
private fun runBuyerAndSeller(notaryNode: StartedNode<MockNetwork.MockNode>,
|
||||
private fun runBuyerAndSeller(notary: Party,
|
||||
sellerNode: StartedNode<MockNetwork.MockNode>,
|
||||
buyerNode: StartedNode<MockNetwork.MockNode>,
|
||||
assetToSell: StateAndRef<OwnableState>,
|
||||
anonymous: Boolean = true): RunResult {
|
||||
val buyerFlows: Observable<out FlowLogic<*>> = buyerNode.internals.registerInitiatedFlow(BuyerAcceptor::class.java)
|
||||
val firstBuyerFiber = buyerFlows.toFuture().map { it.stateMachine }
|
||||
val seller = SellerInitiator(buyerNode.info.chooseIdentity(), notaryNode.info, assetToSell, 1000.DOLLARS, anonymous)
|
||||
val seller = SellerInitiator(buyerNode.info.chooseIdentity(), notary, assetToSell, 1000.DOLLARS, anonymous)
|
||||
val sellerResult = sellerNode.services.startFlow(seller).resultFuture
|
||||
return RunResult(firstBuyerFiber, sellerResult, seller.stateMachine.id)
|
||||
}
|
||||
|
||||
@InitiatingFlow
|
||||
class SellerInitiator(private val buyer: Party,
|
||||
private val notary: NodeInfo,
|
||||
private val notary: Party,
|
||||
private val assetToSell: StateAndRef<OwnableState>,
|
||||
private val price: Amount<Currency>,
|
||||
private val anonymous: Boolean) : FlowLogic<SignedTransaction>() {
|
||||
@ -558,10 +562,9 @@ class TwoPartyTradeFlowTests {
|
||||
} else {
|
||||
ourIdentityAndCert
|
||||
}
|
||||
send(buyer, TestTx(notary.notaryIdentity, price, anonymous))
|
||||
send(buyer, TestTx(notary, price, anonymous))
|
||||
return subFlow(Seller(
|
||||
buyer,
|
||||
notary,
|
||||
assetToSell,
|
||||
price,
|
||||
myPartyAndCert))
|
||||
@ -596,17 +599,18 @@ class TwoPartyTradeFlowTests {
|
||||
|
||||
mockNet.runNetwork()
|
||||
notaryNode.internals.ensureRegistered()
|
||||
val notary = aliceNode.services.getDefaultNotary()
|
||||
|
||||
// Let the nodes know about each other - normally the network map would handle this
|
||||
mockNet.registerIdentities()
|
||||
|
||||
val bobsBadCash = bobNode.database.transaction {
|
||||
fillUpForBuyer(bobError, issuer, bobNode.info.chooseIdentity(),
|
||||
notaryNode.info.notaryIdentity).second
|
||||
notary).second
|
||||
}
|
||||
val alicesFakePaper = aliceNode.database.transaction {
|
||||
fillUpForSeller(aliceError, issuer, aliceNode.info.chooseIdentity(),
|
||||
1200.DOLLARS `issued by` issuer, null, notaryNode.info.notaryIdentity).second
|
||||
1200.DOLLARS `issued by` issuer, null, notary).second
|
||||
}
|
||||
|
||||
insertFakeTransactions(bobsBadCash, bobNode, notaryNode, bankNode)
|
||||
@ -614,7 +618,7 @@ class TwoPartyTradeFlowTests {
|
||||
|
||||
mockNet.runNetwork() // Clear network map registration messages
|
||||
|
||||
val (bobStateMachine, aliceResult) = runBuyerAndSeller(notaryNode, aliceNode, bobNode, "alice's paper".outputStateAndRef())
|
||||
val (bobStateMachine, aliceResult) = runBuyerAndSeller(notary, aliceNode, bobNode, "alice's paper".outputStateAndRef())
|
||||
|
||||
mockNet.runNetwork()
|
||||
|
||||
|
@ -6,7 +6,6 @@ import net.corda.core.flows.NotaryChangeFlow
|
||||
import net.corda.core.flows.StateReplacementException
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
@ -14,6 +13,7 @@ import net.corda.core.utilities.seconds
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.chooseIdentity
|
||||
@ -36,6 +36,8 @@ class NotaryChangeTests {
|
||||
lateinit var newNotaryNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var clientNodeA: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var clientNodeB: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var notaryNewId: Party
|
||||
lateinit var notaryOldId: Party
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
@ -49,6 +51,8 @@ class NotaryChangeTests {
|
||||
mockNet.registerIdentities()
|
||||
mockNet.runNetwork() // Clear network map registration messages
|
||||
oldNotaryNode.internals.ensureRegistered()
|
||||
notaryNewId = newNotaryNode.info.legalIdentities[1]
|
||||
notaryOldId = oldNotaryNode.info.legalIdentities[1]
|
||||
}
|
||||
|
||||
@After
|
||||
@ -58,8 +62,8 @@ class NotaryChangeTests {
|
||||
|
||||
@Test
|
||||
fun `should change notary for a state with single participant`() {
|
||||
val state = issueState(clientNodeA, oldNotaryNode)
|
||||
val newNotary = newNotaryNode.info.notaryIdentity
|
||||
val state = issueState(clientNodeA, oldNotaryNode, notaryOldId)
|
||||
val newNotary = notaryNewId
|
||||
val flow = NotaryChangeFlow(state, newNotary)
|
||||
val future = clientNodeA.services.startFlow(flow)
|
||||
|
||||
@ -71,8 +75,8 @@ class NotaryChangeTests {
|
||||
|
||||
@Test
|
||||
fun `should change notary for a state with multiple participants`() {
|
||||
val state = issueMultiPartyState(clientNodeA, clientNodeB, oldNotaryNode)
|
||||
val newNotary = newNotaryNode.info.notaryIdentity
|
||||
val state = issueMultiPartyState(clientNodeA, clientNodeB, oldNotaryNode, notaryOldId)
|
||||
val newNotary = notaryNewId
|
||||
val flow = NotaryChangeFlow(state, newNotary)
|
||||
val future = clientNodeA.services.startFlow(flow)
|
||||
|
||||
@ -87,7 +91,7 @@ class NotaryChangeTests {
|
||||
|
||||
@Test
|
||||
fun `should throw when a participant refuses to change Notary`() {
|
||||
val state = issueMultiPartyState(clientNodeA, clientNodeB, oldNotaryNode)
|
||||
val state = issueMultiPartyState(clientNodeA, clientNodeB, oldNotaryNode, notaryOldId)
|
||||
val newEvilNotary = getTestPartyAndCertificate(CordaX500Name(organisation = "Evil R3", locality = "London", country = "GB"), generateKeyPair().public)
|
||||
val flow = NotaryChangeFlow(state, newEvilNotary.party)
|
||||
val future = clientNodeA.services.startFlow(flow)
|
||||
@ -101,10 +105,10 @@ class NotaryChangeTests {
|
||||
|
||||
@Test
|
||||
fun `should not break encumbrance links`() {
|
||||
val issueTx = issueEncumberedState(clientNodeA, oldNotaryNode)
|
||||
val issueTx = issueEncumberedState(clientNodeA, notaryOldId)
|
||||
|
||||
val state = StateAndRef(issueTx.outputs.first(), StateRef(issueTx.id, 0))
|
||||
val newNotary = newNotaryNode.info.notaryIdentity
|
||||
val newNotary = notaryNewId
|
||||
val flow = NotaryChangeFlow(state, newNotary)
|
||||
val future = clientNodeA.services.startFlow(flow)
|
||||
mockNet.runNetwork()
|
||||
@ -133,19 +137,17 @@ class NotaryChangeTests {
|
||||
}
|
||||
}
|
||||
|
||||
private fun issueEncumberedState(node: StartedNode<*>, notaryNode: StartedNode<*>): WireTransaction {
|
||||
private fun issueEncumberedState(node: StartedNode<*>, notaryIdentity: Party): WireTransaction {
|
||||
val owner = node.info.chooseIdentity().ref(0)
|
||||
val notary = notaryNode.info.notaryIdentity
|
||||
|
||||
val stateA = DummyContract.SingleOwnerState(Random().nextInt(), owner.party)
|
||||
val stateB = DummyContract.SingleOwnerState(Random().nextInt(), owner.party)
|
||||
val stateC = DummyContract.SingleOwnerState(Random().nextInt(), owner.party)
|
||||
|
||||
val tx = TransactionBuilder(null).apply {
|
||||
addCommand(Command(DummyContract.Commands.Create(), owner.party.owningKey))
|
||||
addOutputState(stateA, DUMMY_PROGRAM_ID, notary, encumbrance = 2) // Encumbered by stateB
|
||||
addOutputState(stateC, DUMMY_PROGRAM_ID, notary)
|
||||
addOutputState(stateB, DUMMY_PROGRAM_ID, notary, encumbrance = 1) // Encumbered by stateC
|
||||
addOutputState(stateA, DUMMY_PROGRAM_ID, notaryIdentity, encumbrance = 2) // Encumbered by stateB
|
||||
addOutputState(stateC, DUMMY_PROGRAM_ID, notaryIdentity)
|
||||
addOutputState(stateB, DUMMY_PROGRAM_ID, notaryIdentity, encumbrance = 1) // Encumbered by stateC
|
||||
}
|
||||
val stx = node.services.signInitialTransaction(tx)
|
||||
node.services.recordTransactions(stx)
|
||||
@ -161,21 +163,21 @@ class NotaryChangeTests {
|
||||
// - The transaction type is not a notary change transaction at all.
|
||||
}
|
||||
|
||||
fun issueState(node: StartedNode<*>, notaryNode: StartedNode<*>): StateAndRef<*> {
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.chooseIdentity().ref(0))
|
||||
fun issueState(node: StartedNode<*>, notaryNode: StartedNode<*>, notaryIdentity: Party): StateAndRef<*> {
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notaryIdentity, node.info.chooseIdentity().ref(0))
|
||||
val signedByNode = node.services.signInitialTransaction(tx)
|
||||
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
|
||||
val stx = notaryNode.services.addSignature(signedByNode, notaryIdentity.owningKey)
|
||||
node.services.recordTransactions(stx)
|
||||
return StateAndRef(tx.outputStates().first(), StateRef(stx.id, 0))
|
||||
}
|
||||
|
||||
fun issueMultiPartyState(nodeA: StartedNode<*>, nodeB: StartedNode<*>, notaryNode: StartedNode<*>): StateAndRef<DummyContract.MultiOwnerState> {
|
||||
fun issueMultiPartyState(nodeA: StartedNode<*>, nodeB: StartedNode<*>, notaryNode: StartedNode<*>, notaryIdentity: Party): StateAndRef<DummyContract.MultiOwnerState> {
|
||||
val state = TransactionState(DummyContract.MultiOwnerState(0,
|
||||
listOf(nodeA.info.chooseIdentity(), nodeB.info.chooseIdentity())), DUMMY_PROGRAM_ID, notaryNode.info.notaryIdentity)
|
||||
val tx = TransactionBuilder(notary = notaryNode.info.notaryIdentity).withItems(state, dummyCommand())
|
||||
listOf(nodeA.info.chooseIdentity(), nodeB.info.chooseIdentity())), DUMMY_PROGRAM_ID, notaryIdentity)
|
||||
val tx = TransactionBuilder(notary = notaryIdentity).withItems(state, dummyCommand())
|
||||
val signedByA = nodeA.services.signInitialTransaction(tx)
|
||||
val signedByAB = nodeB.services.addSignature(signedByA)
|
||||
val stx = notaryNode.services.addSignature(signedByAB, notaryNode.services.notaryIdentityKey)
|
||||
val stx = notaryNode.services.addSignature(signedByAB, notaryIdentity.owningKey)
|
||||
nodeA.services.recordTransactions(stx)
|
||||
nodeB.services.recordTransactions(stx)
|
||||
val stateAndRef = StateAndRef(state, StateRef(stx.id, 0))
|
||||
|
@ -6,7 +6,6 @@ import net.corda.core.contracts.*
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.VaultQueryService
|
||||
import net.corda.core.node.services.queryBy
|
||||
import net.corda.core.node.services.vault.DEFAULT_PAGE_NUM
|
||||
@ -17,6 +16,7 @@ import net.corda.core.node.services.vault.SortAttribute
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.statemachine.StateMachineManager
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
|
@ -4,11 +4,10 @@ import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.node.services.api.ServiceHubInternal
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.messaging.MessagingService
|
||||
import net.corda.node.services.messaging.send
|
||||
|
@ -1,8 +1,8 @@
|
||||
package net.corda.node.services.network
|
||||
|
||||
import net.corda.core.node.services.NetworkMapCache
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.chooseIdentity
|
||||
|
@ -60,8 +60,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||
@Test
|
||||
fun `restart node with DB map cache and no network map`() {
|
||||
val alice = startNodesWithPort(listOf(ALICE), noNetworkMap = true)[0]
|
||||
val partyNodes = alice.services.networkMapCache.partyNodes
|
||||
assertTrue(NetworkMapService.type !in alice.info.advertisedServices.map { it.info.type })
|
||||
val partyNodes = alice.services.networkMapCache.allNodes
|
||||
assertEquals(NullNetworkMapService, alice.inNodeNetworkMapService)
|
||||
assertEquals(infos.size, partyNodes.size)
|
||||
assertEquals(infos.flatMap { it.legalIdentities }.toSet(), partyNodes.flatMap { it.legalIdentities }.toSet())
|
||||
@ -72,9 +71,8 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||
val parties = partiesList.subList(1, partiesList.size)
|
||||
val nodes = startNodesWithPort(parties, noNetworkMap = true)
|
||||
assertTrue(nodes.all { it.inNodeNetworkMapService == NullNetworkMapService })
|
||||
assertTrue(nodes.all { NetworkMapService.type !in it.info.advertisedServices.map { it.info.type } })
|
||||
nodes.forEach {
|
||||
val partyNodes = it.services.networkMapCache.partyNodes
|
||||
val partyNodes = it.services.networkMapCache.allNodes
|
||||
assertEquals(infos.size, partyNodes.size)
|
||||
assertEquals(infos.flatMap { it.legalIdentities }.toSet(), partyNodes.flatMap { it.legalIdentities }.toSet())
|
||||
}
|
||||
@ -86,9 +84,8 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||
val parties = partiesList.subList(1, partiesList.size)
|
||||
val nodes = startNodesWithPort(parties, noNetworkMap = false)
|
||||
assertTrue(nodes.all { it.inNodeNetworkMapService == NullNetworkMapService })
|
||||
assertTrue(nodes.all { NetworkMapService.type !in it.info.advertisedServices.map { it.info.type } })
|
||||
nodes.forEach {
|
||||
val partyNodes = it.services.networkMapCache.partyNodes
|
||||
val partyNodes = it.services.networkMapCache.allNodes
|
||||
assertEquals(infos.size, partyNodes.size)
|
||||
assertEquals(infos.flatMap { it.legalIdentities }.toSet(), partyNodes.flatMap { it.legalIdentities }.toSet())
|
||||
}
|
||||
@ -118,7 +115,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||
// Start node that is not in databases of other nodes. Point to NMS. Which has't started yet.
|
||||
val charlie = startNodesWithPort(listOf(CHARLIE), noNetworkMap = false)[0]
|
||||
otherNodes.forEach {
|
||||
assertThat(it.services.networkMapCache.partyNodes).doesNotContain(charlie.info)
|
||||
assertThat(it.services.networkMapCache.allNodes).doesNotContain(charlie.info)
|
||||
}
|
||||
// Start Network Map and see that charlie node appears in caches.
|
||||
val nms = startNodesWithPort(listOf(DUMMY_NOTARY), noNetworkMap = false)[0]
|
||||
@ -126,13 +123,13 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||
assertTrue(nms.inNodeNetworkMapService != NullNetworkMapService)
|
||||
assertTrue(infos.any { it.legalIdentities.toSet() == nms.info.legalIdentities.toSet() })
|
||||
otherNodes.forEach {
|
||||
assertTrue(nms.info.chooseIdentity() in it.services.networkMapCache.partyNodes.map { it.chooseIdentity() })
|
||||
assertTrue(nms.info.chooseIdentity() in it.services.networkMapCache.allNodes.map { it.chooseIdentity() })
|
||||
}
|
||||
charlie.internals.nodeReadyFuture.get() // Finish registration.
|
||||
checkConnectivity(listOf(otherNodes[0], nms)) // Checks connectivity from A to NMS.
|
||||
val cacheA = otherNodes[0].services.networkMapCache.partyNodes
|
||||
val cacheB = otherNodes[1].services.networkMapCache.partyNodes
|
||||
val cacheC = charlie.services.networkMapCache.partyNodes
|
||||
val cacheA = otherNodes[0].services.networkMapCache.allNodes
|
||||
val cacheB = otherNodes[1].services.networkMapCache.allNodes
|
||||
val cacheC = charlie.services.networkMapCache.allNodes
|
||||
assertEquals(4, cacheC.size) // Charlie fetched data from NetworkMap
|
||||
assertThat(cacheB).contains(charlie.info)
|
||||
assertEquals(cacheA.toSet(), cacheB.toSet())
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.corda.node.services.network
|
||||
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.api.ServiceHubInternal
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.testing.node.MockNetwork
|
||||
|
@ -15,7 +15,6 @@ import net.corda.core.internal.concurrent.flatMap
|
||||
import net.corda.core.internal.concurrent.map
|
||||
import net.corda.core.messaging.MessageRecipients
|
||||
import net.corda.core.node.services.PartyInfo
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.queryBy
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
@ -32,6 +31,7 @@ import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.node.internal.InitiatedFlowFactory
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.persistence.checkpoints
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
@ -72,6 +72,8 @@ class FlowFrameworkTests {
|
||||
private lateinit var node2: StartedNode<MockNode>
|
||||
private lateinit var notary1: StartedNode<MockNode>
|
||||
private lateinit var notary2: StartedNode<MockNode>
|
||||
private lateinit var notary1Identity: Party
|
||||
private lateinit var notary2Identity: Party
|
||||
|
||||
@Before
|
||||
fun start() {
|
||||
@ -95,6 +97,8 @@ class FlowFrameworkTests {
|
||||
|
||||
// We don't create a network map, so manually handle registrations
|
||||
mockNet.registerIdentities()
|
||||
notary1Identity = notary1.services.myInfo.legalIdentities[1]
|
||||
notary2Identity = notary2.services.myInfo.legalIdentities[1]
|
||||
}
|
||||
|
||||
@After
|
||||
@ -333,11 +337,12 @@ class FlowFrameworkTests {
|
||||
|
||||
@Test
|
||||
fun `different notaries are picked when addressing shared notary identity`() {
|
||||
assertEquals(notary1.info.notaryIdentity, notary2.info.notaryIdentity)
|
||||
assertEquals(notary1Identity, notary2Identity)
|
||||
assertThat(node1.services.networkMapCache.notaryIdentities.size == 1)
|
||||
node1.services.startFlow(CashIssueFlow(
|
||||
2000.DOLLARS,
|
||||
OpaqueBytes.of(0x01),
|
||||
notary1.info.notaryIdentity)).resultFuture.getOrThrow()
|
||||
notary1Identity)).resultFuture.getOrThrow()
|
||||
// We pay a couple of times, the notary picking should go round robin
|
||||
for (i in 1..3) {
|
||||
val flow = node1.services.startFlow(CashPaymentFlow(500.DOLLARS, node2.info.chooseIdentity()))
|
||||
@ -345,11 +350,11 @@ class FlowFrameworkTests {
|
||||
flow.resultFuture.getOrThrow()
|
||||
}
|
||||
val endpoint = mockNet.messagingNetwork.endpoint(notary1.network.myAddress as InMemoryMessagingNetwork.PeerHandle)!!
|
||||
val party1Info = notary1.services.networkMapCache.getPartyInfo(notary1.info.notaryIdentity)!!
|
||||
val party1Info = notary1.services.networkMapCache.getPartyInfo(notary1Identity)!!
|
||||
assertTrue(party1Info is PartyInfo.DistributedNode)
|
||||
val notary1Address: MessageRecipients = endpoint.getAddressOfParty(notary1.services.networkMapCache.getPartyInfo(notary1.info.notaryIdentity)!!)
|
||||
val notary1Address: MessageRecipients = endpoint.getAddressOfParty(notary1.services.networkMapCache.getPartyInfo(notary1Identity)!!)
|
||||
assertThat(notary1Address).isInstanceOf(InMemoryMessagingNetwork.ServiceHandle::class.java)
|
||||
assertEquals(notary1Address, endpoint.getAddressOfParty(notary2.services.networkMapCache.getPartyInfo(notary2.info.notaryIdentity)!!))
|
||||
assertEquals(notary1Address, endpoint.getAddressOfParty(notary2.services.networkMapCache.getPartyInfo(notary2Identity)!!))
|
||||
receivedSessionMessages.expectEvents(isStrict = false) {
|
||||
sequence(
|
||||
// First Pay
|
||||
@ -598,7 +603,7 @@ class FlowFrameworkTests {
|
||||
|
||||
@Test
|
||||
fun `wait for transaction`() {
|
||||
val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity)
|
||||
val ptx = TransactionBuilder(notary = notary1Identity)
|
||||
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
|
||||
.addCommand(dummyCommand(node1.info.chooseIdentity().owningKey))
|
||||
val stx = node1.services.signInitialTransaction(ptx)
|
||||
@ -613,7 +618,7 @@ class FlowFrameworkTests {
|
||||
|
||||
@Test
|
||||
fun `committer throws exception before calling the finality flow`() {
|
||||
val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity)
|
||||
val ptx = TransactionBuilder(notary = notary1Identity)
|
||||
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
|
||||
.addCommand(dummyCommand())
|
||||
val stx = node1.services.signInitialTransaction(ptx)
|
||||
@ -630,7 +635,7 @@ class FlowFrameworkTests {
|
||||
|
||||
@Test
|
||||
fun `verify vault query service is tokenizable by force checkpointing within a flow`() {
|
||||
val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity)
|
||||
val ptx = TransactionBuilder(notary = notary1Identity)
|
||||
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
|
||||
.addCommand(dummyCommand(node1.info.chooseIdentity().owningKey))
|
||||
val stx = node1.services.signInitialTransaction(ptx)
|
||||
|
@ -7,17 +7,19 @@ import net.corda.core.crypto.TransactionSignature
|
||||
import net.corda.core.flows.NotaryError
|
||||
import net.corda.core.flows.NotaryException
|
||||
import net.corda.core.flows.NotaryFlow
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.seconds
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.After
|
||||
@ -32,6 +34,7 @@ class NotaryServiceTests {
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var clientNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var notary: Party
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
@ -42,6 +45,7 @@ class NotaryServiceTests {
|
||||
clientNode = mockNet.createNode(notaryNode.network.myAddress)
|
||||
mockNet.runNetwork() // Clear network map registration messages
|
||||
notaryNode.internals.ensureRegistered()
|
||||
notary = clientNode.services.getDefaultNotary()
|
||||
}
|
||||
|
||||
@After
|
||||
@ -53,7 +57,7 @@ class NotaryServiceTests {
|
||||
fun `should sign a unique transaction with a valid time-window`() {
|
||||
val stx = run {
|
||||
val inputState = issueState(clientNode)
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
val tx = TransactionBuilder(notary)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
.setTimeWindow(Instant.now(), 30.seconds)
|
||||
@ -69,7 +73,7 @@ class NotaryServiceTests {
|
||||
fun `should sign a unique transaction without a time-window`() {
|
||||
val stx = run {
|
||||
val inputState = issueState(clientNode)
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
val tx = TransactionBuilder(notary)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
clientNode.services.signInitialTransaction(tx)
|
||||
@ -84,7 +88,7 @@ class NotaryServiceTests {
|
||||
fun `should report error for transaction with an invalid time-window`() {
|
||||
val stx = run {
|
||||
val inputState = issueState(clientNode)
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
val tx = TransactionBuilder(notary)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
.setTimeWindow(Instant.now().plusSeconds(3600), 30.seconds)
|
||||
@ -101,7 +105,7 @@ class NotaryServiceTests {
|
||||
fun `should sign identical transaction multiple times (signing is idempotent)`() {
|
||||
val stx = run {
|
||||
val inputState = issueState(clientNode)
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
val tx = TransactionBuilder(notary)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
clientNode.services.signInitialTransaction(tx)
|
||||
@ -121,13 +125,13 @@ class NotaryServiceTests {
|
||||
fun `should report conflict when inputs are reused across transactions`() {
|
||||
val inputState = issueState(clientNode)
|
||||
val stx = run {
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
val tx = TransactionBuilder(notary)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
clientNode.services.signInitialTransaction(tx)
|
||||
}
|
||||
val stx2 = run {
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
val tx = TransactionBuilder(notary)
|
||||
.addInputState(inputState)
|
||||
.addInputState(issueState(clientNode))
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
@ -155,7 +159,7 @@ class NotaryServiceTests {
|
||||
}
|
||||
|
||||
fun issueState(node: StartedNode<*>): StateAndRef<*> {
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.chooseIdentity().ref(0))
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notary, node.info.chooseIdentity().ref(0))
|
||||
val signedByNode = node.services.signInitialTransaction(tx)
|
||||
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
|
||||
node.services.recordTransactions(stx)
|
||||
|
@ -8,11 +8,12 @@ import net.corda.core.crypto.TransactionSignature
|
||||
import net.corda.core.flows.NotaryError
|
||||
import net.corda.core.flows.NotaryException
|
||||
import net.corda.core.flows.NotaryFlow
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.issueInvalidState
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
@ -20,6 +21,7 @@ import net.corda.testing.MEGA_CORP_KEY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.After
|
||||
@ -33,6 +35,7 @@ class ValidatingNotaryServiceTests {
|
||||
lateinit var mockNet: MockNetwork
|
||||
lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var clientNode: StartedNode<MockNetwork.MockNode>
|
||||
lateinit var notary: Party
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
@ -44,6 +47,7 @@ class ValidatingNotaryServiceTests {
|
||||
clientNode = mockNet.createNode(notaryNode.network.myAddress)
|
||||
mockNet.runNetwork() // Clear network map registration messages
|
||||
notaryNode.internals.ensureRegistered()
|
||||
notary = clientNode.services.getDefaultNotary()
|
||||
}
|
||||
|
||||
@After
|
||||
@ -54,8 +58,8 @@ class ValidatingNotaryServiceTests {
|
||||
@Test
|
||||
fun `should report error for invalid transaction dependency`() {
|
||||
val stx = run {
|
||||
val inputState = issueInvalidState(clientNode, notaryNode.info.notaryIdentity)
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
val inputState = issueInvalidState(clientNode, notary)
|
||||
val tx = TransactionBuilder(notary)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
clientNode.services.signInitialTransaction(tx)
|
||||
@ -75,7 +79,7 @@ class ValidatingNotaryServiceTests {
|
||||
val inputState = issueState(clientNode)
|
||||
|
||||
val command = Command(DummyContract.Commands.Move(), expectedMissingKey)
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState, command)
|
||||
val tx = TransactionBuilder(notary).withItems(inputState, command)
|
||||
clientNode.services.signInitialTransaction(tx)
|
||||
}
|
||||
|
||||
@ -98,7 +102,7 @@ class ValidatingNotaryServiceTests {
|
||||
}
|
||||
|
||||
fun issueState(node: StartedNode<*>): StateAndRef<*> {
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.chooseIdentity().ref(0))
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notary, node.info.chooseIdentity().ref(0))
|
||||
val signedByNode = node.services.signInitialTransaction(tx)
|
||||
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
|
||||
node.services.recordTransactions(stx)
|
||||
|
@ -1,8 +1,8 @@
|
||||
package net.corda.attachmentdemo
|
||||
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.corda.attachmentdemo
|
||||
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_BANK_B
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
|
@ -2,8 +2,8 @@ package net.corda.bank
|
||||
|
||||
import net.corda.bank.api.BankOfCordaClientApi
|
||||
import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.testing.BOC
|
||||
import net.corda.testing.driver.driver
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.corda.bank
|
||||
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.Vault
|
||||
import net.corda.core.node.services.vault.QueryCriteria
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
@ -9,6 +8,7 @@ import net.corda.finance.DOLLARS
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.*
|
||||
@ -33,6 +33,8 @@ class BankOfCordaRPCClientTest {
|
||||
// Big Corporation RPC Client
|
||||
val bigCorpClient = nodeBigCorporation.rpcClientToNode()
|
||||
val bigCorpProxy = bigCorpClient.start("bigCorpCFO", "password2").proxy
|
||||
bocProxy.waitUntilNetworkReady()
|
||||
bigCorpProxy.waitUntilNetworkReady()
|
||||
|
||||
// Register for Bank of Corda Vault updates
|
||||
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)
|
||||
@ -43,11 +45,12 @@ class BankOfCordaRPCClientTest {
|
||||
|
||||
// Kick-off actual Issuer Flow
|
||||
val anonymous = true
|
||||
val notary = bocProxy.notaryIdentities().first().party
|
||||
bocProxy.startFlow(::CashIssueAndPaymentFlow,
|
||||
1000.DOLLARS, BIG_CORP_PARTY_REF,
|
||||
nodeBigCorporation.nodeInfo.chooseIdentity(),
|
||||
anonymous,
|
||||
nodeBankOfCorda.nodeInfo.notaryIdentity).returnValue.getOrThrow()
|
||||
notary).returnValue.getOrThrow()
|
||||
|
||||
// Check Bank of Corda Vault Updates
|
||||
vaultUpdatesBoc.expectEvents {
|
||||
|
@ -4,13 +4,12 @@ import joptsimple.OptionParser
|
||||
import net.corda.bank.api.BankOfCordaClientApi
|
||||
import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.finance.flows.CashExitFlow
|
||||
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
||||
import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.BOC
|
||||
@ -74,8 +73,7 @@ private class BankOfCordaDriver {
|
||||
advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type)))
|
||||
val bankOfCorda = startNode(
|
||||
providedName = BOC.name,
|
||||
rpcUsers = listOf(bankUser),
|
||||
advertisedServices = setOf(ServiceInfo(ServiceType.corda.getSubType("issuer.USD"))))
|
||||
rpcUsers = listOf(bankUser))
|
||||
startNode(providedName = BIGCORP_LEGAL_NAME, rpcUsers = listOf(bigCorpUser))
|
||||
startWebserver(bankOfCorda.get())
|
||||
waitForAllNodesToFinish()
|
||||
|
@ -36,20 +36,19 @@ class BankOfCordaClientApi(val hostAndPort: NetworkHostAndPort) {
|
||||
// TODO: privileged security controls required
|
||||
client.start("bankUser", "test").use { connection ->
|
||||
val rpc = connection.proxy
|
||||
rpc.waitUntilNetworkReady()
|
||||
|
||||
// Resolve parties via RPC
|
||||
val issueToParty = rpc.partyFromX500Name(params.issueToPartyName)
|
||||
?: throw Exception("Unable to locate ${params.issueToPartyName} in Network Map Service")
|
||||
val notaryLegalIdentity = rpc.partyFromX500Name(params.notaryName)
|
||||
?: throw IllegalStateException("Unable to locate ${params.notaryName} in Network Map Service")
|
||||
val notaryNode = rpc.nodeIdentityFromParty(notaryLegalIdentity)
|
||||
?: throw IllegalStateException("Unable to locate notary node in network map cache")
|
||||
|
||||
val amount = Amount(params.amount, Currency.getInstance(params.currency))
|
||||
val anonymous = true
|
||||
val issuerBankPartyRef = OpaqueBytes.of(params.issuerBankPartyRef.toByte())
|
||||
|
||||
return rpc.startFlow(::CashIssueAndPaymentFlow, amount, issuerBankPartyRef, issueToParty, anonymous, notaryNode.notaryIdentity)
|
||||
return rpc.startFlow(::CashIssueAndPaymentFlow, amount, issuerBankPartyRef, issueToParty, anonymous, notaryLegalIdentity)
|
||||
.returnValue.getOrThrow().stx
|
||||
}
|
||||
}
|
||||
|
@ -46,8 +46,6 @@ class BankOfCordaWebApi(val rpc: CordaRPCOps) {
|
||||
rpc.partyFromX500Name(params.issuerBankName) ?: return Response.status(Response.Status.FORBIDDEN).entity("Unable to locate ${params.issuerBankName} in identity service").build()
|
||||
val notaryParty = rpc.partyFromX500Name(params.notaryName)
|
||||
?: return Response.status(Response.Status.FORBIDDEN).entity("Unable to locate ${params.notaryName} in identity service").build()
|
||||
val notaryNode = rpc.nodeIdentityFromParty(notaryParty)
|
||||
?: return Response.status(Response.Status.FORBIDDEN).entity("Unable to locate $notaryParty in network map service").build()
|
||||
|
||||
val amount = Amount(params.amount, Currency.getInstance(params.currency))
|
||||
val anonymous = true
|
||||
@ -56,7 +54,7 @@ class BankOfCordaWebApi(val rpc: CordaRPCOps) {
|
||||
// invoke client side of Issuer Flow: IssuanceRequester
|
||||
// The line below blocks and waits for the future to resolve.
|
||||
return try {
|
||||
rpc.startFlow(::CashIssueAndPaymentFlow, amount, issuerBankPartyRef, issueToParty, anonymous, notaryNode.notaryIdentity).returnValue.getOrThrow()
|
||||
rpc.startFlow(::CashIssueAndPaymentFlow, amount, issuerBankPartyRef, issueToParty, anonymous, notaryParty).returnValue.getOrThrow()
|
||||
logger.info("Issue and payment request completed successfully: $params")
|
||||
Response.status(Response.Status.CREATED).build()
|
||||
} catch (e: Exception) {
|
||||
|
@ -12,7 +12,6 @@ import net.corda.client.rpc.CordaRPCClient
|
||||
import net.corda.core.contracts.UniqueIdentifier
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.messaging.vaultTrackBy
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.toFuture
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
@ -21,6 +20,7 @@ import net.corda.core.utilities.seconds
|
||||
import net.corda.finance.plugin.registerFinanceJSONMappers
|
||||
import net.corda.irs.contract.InterestRateSwap
|
||||
import net.corda.irs.utilities.uploadFile
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.config.FullNodeConfiguration
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
|
@ -47,8 +47,8 @@ object AutoOfferFlow {
|
||||
|
||||
@Suspendable
|
||||
override fun call(): SignedTransaction {
|
||||
require(serviceHub.networkMapCache.notaryNodes.isNotEmpty()) { "No notary nodes registered" }
|
||||
val notary = serviceHub.networkMapCache.notaryNodes.first().notaryIdentity
|
||||
require(serviceHub.networkMapCache.notaryIdentities.isNotEmpty()) { "No notary nodes registered" }
|
||||
val notary = serviceHub.networkMapCache.notaryIdentities.first().party // TODO We should pass the notary as a parameter to the flow, not leave it to random choice.
|
||||
// need to pick which ever party is not us
|
||||
val otherParty = notUs(dealToBeOffered.participants).map { serviceHub.identityService.partyFromAnonymous(it) }.requireNoNulls().single()
|
||||
progressTracker.currentStep = DEALING
|
||||
|
@ -100,9 +100,7 @@ object FixingFlow {
|
||||
StateAndRef(state, payload.ref)
|
||||
}
|
||||
|
||||
override val notaryNode: NodeInfo get() {
|
||||
return serviceHub.networkMapCache.notaryNodes.single { it.notaryIdentity == dealToFix.state.notary }
|
||||
}
|
||||
override val notaryParty: Party get() = dealToFix.state.notary
|
||||
|
||||
@Suspendable override fun checkProposal(stx: SignedTransaction) = requireThat {
|
||||
// Add some constraints here.
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.corda.irs
|
||||
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_BANK_B
|
||||
|
@ -54,9 +54,11 @@ object UpdateBusinessDayFlow {
|
||||
* the notary or counterparty still use the old clock, so the time-window on the transaction does not validate.
|
||||
*/
|
||||
private fun getRecipients(): Iterable<Party> {
|
||||
val notaryNodes = serviceHub.networkMapCache.notaryNodes.map { it.legalIdentitiesAndCerts.first().party } // TODO Will break on distributed nodes, but it will change after services removal.
|
||||
val partyNodes = (serviceHub.networkMapCache.partyNodes.map { it.legalIdentitiesAndCerts.first().party } - notaryNodes).sortedBy { it.name.toString() }
|
||||
return notaryNodes + partyNodes
|
||||
val notaryParties = serviceHub.networkMapCache.notaryIdentities.map { it.party }
|
||||
val peerParties = serviceHub.networkMapCache.allNodes.filter {
|
||||
it.legalIdentities.all { !serviceHub.networkMapCache.isNotary(it) }
|
||||
}.map { it.legalIdentities[0] }.sortedBy { it.name.toString() }
|
||||
return notaryParties + peerParties
|
||||
}
|
||||
|
||||
@Suspendable
|
||||
|
@ -138,6 +138,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
|
||||
node1.internals.registerInitiatedFlow(FixingFlow.Fixer::class.java)
|
||||
node2.internals.registerInitiatedFlow(FixingFlow.Fixer::class.java)
|
||||
|
||||
val notaryId = node1.rpcOps.notaryIdentities().first().party
|
||||
@InitiatingFlow
|
||||
class StartDealFlow(val otherParty: Party,
|
||||
val payload: AutoOffer) : FlowLogic<SignedTransaction>() {
|
||||
@ -160,7 +161,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
|
||||
|
||||
val instigator = StartDealFlow(
|
||||
node2.info.chooseIdentity(),
|
||||
AutoOffer(notary.info.notaryIdentity, irs))
|
||||
AutoOffer(notaryId, irs)) // TODO Pass notary as parameter to Simulation.
|
||||
val instigatorTxFuture = node1.services.startFlow(instigator).resultFuture
|
||||
|
||||
return allOf(instigatorTxFuture.toCompletableFuture(), acceptorTxFuture).thenCompose { instigatorTxFuture.toCompletableFuture() }
|
||||
|
@ -6,11 +6,11 @@ import net.corda.finance.utils.CityDatabase
|
||||
import net.corda.finance.utils.WorldMapLocation
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.irs.api.NodeInterestRates
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.nodeapi.ServiceType
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.statemachine.StateMachineManager
|
||||
|
@ -7,8 +7,8 @@ import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.stream
|
||||
import net.corda.core.internal.toTypedArray
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.BFTNonValidatingNotaryService
|
||||
import net.corda.node.services.transactions.minCorrectReplicas
|
||||
import net.corda.node.utilities.ServiceIdentityGenerator
|
||||
|
@ -26,8 +26,7 @@ fun main(args: Array<String>) {
|
||||
/** Interface for using the notary demo API from a client. */
|
||||
private class NotaryDemoClientApi(val rpc: CordaRPCOps) {
|
||||
private val notary by lazy {
|
||||
val parties = rpc.networkMapSnapshot()
|
||||
val id = parties.stream().filter { it.advertisedServices.any { it.info.type.isNotary() } }.map { it.notaryIdentity }.distinct().asSequence().singleOrNull()
|
||||
val id = rpc.notaryIdentities().distinct().singleOrNull()?.party
|
||||
checkNotNull(id) { "No unique notary identity, try cleaning the node directories." }
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@ import net.corda.cordform.CordformDefinition
|
||||
import net.corda.cordform.CordformNode
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.RaftValidatingNotaryService
|
||||
import net.corda.node.utilities.ServiceIdentityGenerator
|
||||
import net.corda.testing.ALICE
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.corda.notarydemo
|
||||
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
@ -12,6 +11,7 @@ import net.corda.notarydemo.flows.DummyIssueAndMove
|
||||
import net.corda.notarydemo.flows.RPCStartableNotaryFlowClient
|
||||
import net.corda.cordform.CordformDefinition
|
||||
import net.corda.cordform.CordformContext
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.testing.internal.demorun.*
|
||||
|
||||
fun main(args: Array<String>) = SingleNotaryCordform.runNodes()
|
||||
|
@ -2,8 +2,8 @@ package net.corda.vega
|
||||
|
||||
import com.opengamma.strata.product.common.BuySell
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_BANK_B
|
||||
|
@ -10,7 +10,6 @@ import net.corda.core.identity.Party
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.messaging.vaultQueryBy
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.finance.contracts.DealState
|
||||
import net.corda.vega.analytics.InitialMarginTriple
|
||||
@ -22,7 +21,6 @@ import net.corda.vega.flows.SimmRevaluation
|
||||
import net.corda.vega.portfolio.Portfolio
|
||||
import net.corda.vega.portfolio.toPortfolio
|
||||
import net.corda.vega.portfolio.toStateAndRef
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
@ -254,11 +252,11 @@ class PortfolioApi(val rpc: CordaRPCOps) {
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
fun getWhoAmI(): AvailableParties {
|
||||
val parties = rpc.networkMapSnapshot()
|
||||
val counterParties = parties.filterNot {
|
||||
it.advertisedServices.any { it.info.type in setOf(ServiceType.networkMap, ServiceType.notary) }
|
||||
|| ownParty in it.legalIdentitiesAndCerts.map { it.party }
|
||||
val notaries = rpc.notaryIdentities()
|
||||
// TODO We are not able to filter by network map node now
|
||||
val counterParties = parties.filterNot { it.legalIdentitiesAndCerts.any { it in notaries }
|
||||
|| ownParty in it.legalIdentities
|
||||
}
|
||||
|
||||
return AvailableParties(
|
||||
self = ApiParty(ownParty.owningKey.toBase58String(), ownParty.name),
|
||||
// TODO It will show all identities including service identities.
|
||||
|
@ -22,8 +22,8 @@ object IRSTradeFlow {
|
||||
class Requester(val swap: SwapData, val otherParty: Party) : FlowLogic<SignedTransaction>() {
|
||||
@Suspendable
|
||||
override fun call(): SignedTransaction {
|
||||
require(serviceHub.networkMapCache.notaryNodes.isNotEmpty()) { "No notary nodes registered" }
|
||||
val notary = serviceHub.networkMapCache.notaryNodes.first().notaryIdentity
|
||||
require(serviceHub.networkMapCache.notaryIdentities.isNotEmpty()) { "No notary nodes registered" }
|
||||
val notary = serviceHub.networkMapCache.notaryIdentities.first().party // TODO We should pass the notary as a parameter to the flow, not leave it to random choice.
|
||||
val (buyer, seller) =
|
||||
if (swap.buyer.second == ourIdentity.owningKey) {
|
||||
Pair(ourIdentity, otherParty)
|
||||
@ -52,7 +52,7 @@ object IRSTradeFlow {
|
||||
|
||||
val offer = receive<OfferMessage>(replyToParty).unwrap { it }
|
||||
// Automatically agree - in reality we'd vet the offer message
|
||||
require(serviceHub.networkMapCache.notaryNodes.map { it.notaryIdentity }.contains(offer.notary))
|
||||
require(serviceHub.networkMapCache.notaryIdentities.map { it.party }.contains(offer.notary))
|
||||
send(replyToParty, true)
|
||||
subFlow(TwoPartyDealFlow.Acceptor(replyToParty))
|
||||
}
|
||||
|
@ -61,8 +61,8 @@ object SimmFlow {
|
||||
@Suspendable
|
||||
override fun call(): RevisionedState<PortfolioState.Update> {
|
||||
logger.debug("Calling from: $ourIdentity. Sending to: $otherParty")
|
||||
require(serviceHub.networkMapCache.notaryNodes.isNotEmpty()) { "No notary nodes registered" }
|
||||
notary = serviceHub.networkMapCache.notaryNodes.first().notaryIdentity
|
||||
require(serviceHub.networkMapCache.notaryIdentities.isNotEmpty()) { "No notary nodes registered" }
|
||||
notary = serviceHub.networkMapCache.notaryIdentities.first().party // TODO We should pass the notary as a parameter to the flow, not leave it to random choice.
|
||||
|
||||
val criteria = LinearStateQueryCriteria(participants = listOf(otherParty))
|
||||
val trades = serviceHub.vaultQueryService.queryBy<IRSState>(criteria).states
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.corda.vega
|
||||
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_BANK_B
|
||||
import net.corda.testing.DUMMY_BANK_C
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.corda.traderdemo
|
||||
|
||||
import net.corda.client.rpc.CordaRPCClient
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.millis
|
||||
import net.corda.finance.DOLLARS
|
||||
@ -10,6 +9,7 @@ import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.finance.schemas.CashSchemaV1
|
||||
import net.corda.finance.schemas.CommercialPaperSchemaV1
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.BOC
|
||||
|
@ -46,12 +46,10 @@ class TraderDemoClientApi(val rpc: CordaRPCOps) {
|
||||
val ref = OpaqueBytes.of(1)
|
||||
val buyer = rpc.partyFromX500Name(buyerName) ?: throw IllegalStateException("Don't know $buyerName")
|
||||
val seller = rpc.partyFromX500Name(sellerName) ?: throw IllegalStateException("Don't know $sellerName")
|
||||
val notaryLegalIdentity = rpc.partyFromX500Name(DUMMY_NOTARY.name)
|
||||
?: throw IllegalStateException("Unable to locate ${DUMMY_NOTARY.name} in Network Map Service")
|
||||
val notaryNode = rpc.nodeIdentityFromParty(notaryLegalIdentity)
|
||||
?: throw IllegalStateException("Unable to locate notary node in network map cache")
|
||||
val notaryIdentity = rpc.notaryIdentities().first().party
|
||||
|
||||
val amounts = calculateRandomlySizedAmounts(amount, 3, 10, Random())
|
||||
rpc.startFlow(::CashIssueFlow, amount, OpaqueBytes.of(1), notaryNode.notaryIdentity).returnValue.getOrThrow()
|
||||
rpc.startFlow(::CashIssueFlow, amount, OpaqueBytes.of(1), notaryIdentity).returnValue.getOrThrow()
|
||||
// Pay random amounts of currency up to the requested amount
|
||||
amounts.forEach { pennies ->
|
||||
// TODO This can't be done in parallel, perhaps due to soft-locking issues?
|
||||
@ -71,7 +69,7 @@ class TraderDemoClientApi(val rpc: CordaRPCOps) {
|
||||
}
|
||||
|
||||
// The line below blocks and waits for the future to resolve.
|
||||
rpc.startFlow(::CommercialPaperIssueFlow, amount, ref, seller, notaryNode.notaryIdentity).returnValue.getOrThrow()
|
||||
rpc.startFlow(::CommercialPaperIssueFlow, amount, ref, seller, notaryIdentity).returnValue.getOrThrow()
|
||||
println("Commercial paper issued to seller")
|
||||
}
|
||||
|
||||
|
@ -29,10 +29,11 @@ class BuyerFlow(val otherParty: Party) : FlowLogic<Unit>() {
|
||||
|
||||
// Receive the offered amount and automatically agree to it (in reality this would be a longer negotiation)
|
||||
val amount = receive<Amount<Currency>>(otherParty).unwrap { it }
|
||||
val notary: NodeInfo = serviceHub.networkMapCache.notaryNodes[0]
|
||||
require(serviceHub.networkMapCache.notaryIdentities.isNotEmpty()) { "No notary nodes registered" }
|
||||
val notary: Party = serviceHub.networkMapCache.notaryIdentities[0].party
|
||||
val buyer = TwoPartyTradeFlow.Buyer(
|
||||
otherParty,
|
||||
notary.notaryIdentity,
|
||||
notary,
|
||||
amount,
|
||||
CommercialPaper.State::class.java)
|
||||
|
||||
|
@ -40,7 +40,7 @@ class SellerFlow(private val otherParty: Party,
|
||||
override fun call(): SignedTransaction {
|
||||
progressTracker.currentStep = SELF_ISSUING
|
||||
|
||||
val notary: NodeInfo = serviceHub.networkMapCache.notaryNodes[0]
|
||||
val notary: Party = serviceHub.networkMapCache.notaryIdentities[0].party
|
||||
val cpOwner = serviceHub.keyManagementService.freshKeyAndCert(ourIdentityAndCert, false)
|
||||
val commercialPaper = serviceHub.vaultQueryService.queryBy(CommercialPaper.State::class.java).states.first()
|
||||
|
||||
@ -50,7 +50,6 @@ class SellerFlow(private val otherParty: Party,
|
||||
send(otherParty, amount)
|
||||
val seller = TwoPartyTradeFlow.Seller(
|
||||
otherParty,
|
||||
notary,
|
||||
commercialPaper,
|
||||
amount,
|
||||
cpOwner,
|
||||
|
@ -1,9 +1,9 @@
|
||||
package net.corda.traderdemo
|
||||
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.BOC
|
||||
|
@ -3,14 +3,13 @@ package net.corda.testing.driver
|
||||
import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.list
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.internal.readLines
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.DUMMY_REGULATOR
|
||||
import net.corda.node.internal.NodeStartup
|
||||
import net.corda.node.services.api.RegulatorService
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.testing.ProjectStructure.projectRootDir
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
@ -42,7 +41,7 @@ class DriverTests {
|
||||
fun `simple node startup and shutdown`() {
|
||||
val handles = driver {
|
||||
val notary = startNode(providedName = DUMMY_NOTARY.name, advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type)))
|
||||
val regulator = startNode(providedName = DUMMY_REGULATOR.name, advertisedServices = setOf(ServiceInfo(RegulatorService.type)))
|
||||
val regulator = startNode(providedName = DUMMY_REGULATOR.name)
|
||||
listOf(nodeMustBeUp(notary), nodeMustBeUp(regulator))
|
||||
}
|
||||
handles.map { nodeMustBeDown(it) }
|
||||
|
@ -24,6 +24,7 @@ import net.corda.testing.node.MockAttachmentStorage
|
||||
import net.corda.testing.node.MockNetworkMapCache
|
||||
import net.corda.testing.node.MockStateMachineRecordedTransactionMappingStorage
|
||||
import net.corda.testing.node.MockTransactionStorage
|
||||
import java.security.PublicKey
|
||||
import java.sql.Connection
|
||||
import java.time.Clock
|
||||
|
||||
@ -67,6 +68,8 @@ open class MockServiceHubInternal(
|
||||
get() = overrideClock ?: throw UnsupportedOperationException()
|
||||
override val myInfo: NodeInfo
|
||||
get() = NodeInfo(listOf(MOCK_HOST_AND_PORT), listOf(DUMMY_IDENTITY_1), 1, serial = 1L) // Required to get a dummy platformVersion when required for tests.
|
||||
override val notaryIdentityKey: PublicKey
|
||||
get() = throw IllegalStateException("No notary identity in MockServiceHubInternal")
|
||||
override val monitoringService: MonitoringService = MonitoringService(MetricRegistry())
|
||||
override val rpcFlows: List<Class<out FlowLogic<*>>>
|
||||
get() = throw UnsupportedOperationException()
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user