NodeInfo remove main identity (#1284)

* Remove node's main identitiy from NodeInfo.

Preparation for getting rid of services + supporting multiple identities
on the node.
NodeInfo keeps multiple identities as a list. For now the first one is treated as a special one.
Introduced function chooseIdentity in CoreTestUtils as a preparation for proper handling of multiple identities in the future.
Remove legalIdentityKey from ServiceHub, add extension function - chooseIdentity on ServiceHub.
Add `me` field on FlowStateMachineImplemetation, flows should know what the calling identity is.
Remove SERVICES_PREFIX in artemis messaging layer.

* Address minor comments.

* Fixes after rebase.

Remove chooseIdentity from ServiceHub

* Rename me to ourIdentity on FlowLogic

* Fixes after rebase

* Address Ross comments, fixes

* Fix after rebase

* Fix services certificate paths

Apply Patrick's patch.
This commit is contained in:
Katarzyna Streich 2017-09-15 14:39:34 +01:00 committed by josecoll
parent d747f71fe5
commit 495e870b74
144 changed files with 804 additions and 692 deletions

View File

@ -94,13 +94,13 @@ class NodeMonitorModelTest : DriverBasedTest() {
sequence(
// TODO : Add test for remove when driver DSL support individual node shutdown.
expect { output: NetworkMapCache.MapChange ->
require(output.node.legalIdentity.name == ALICE.name) { "Expecting : ${ALICE.name}, Actual : ${output.node.legalIdentity.name}" }
require(output.node.chooseIdentity().name == ALICE.name) { "Expecting : ${ALICE.name}, Actual : ${output.node.chooseIdentity().name}" }
},
expect { output: NetworkMapCache.MapChange ->
require(output.node.legalIdentity.name == BOB.name) { "Expecting : ${BOB.name}, Actual : ${output.node.legalIdentity.name}" }
require(output.node.chooseIdentity().name == BOB.name) { "Expecting : ${BOB.name}, Actual : ${output.node.chooseIdentity().name}" }
},
expect { output: NetworkMapCache.MapChange ->
require(output.node.legalIdentity.name == CHARLIE.name) { "Expecting : ${CHARLIE.name}, Actual : ${output.node.legalIdentity.name}" }
require(output.node.chooseIdentity().name == CHARLIE.name) { "Expecting : ${CHARLIE.name}, Actual : ${output.node.chooseIdentity().name}" }
}
)
}
@ -134,7 +134,7 @@ class NodeMonitorModelTest : DriverBasedTest() {
fun `cash issue and move`() {
val anonymous = false
val (_, issueIdentity) = rpc.startFlow(::CashIssueFlow, 100.DOLLARS, OpaqueBytes.of(1), notaryNode.notaryIdentity).returnValue.getOrThrow()
val (_, paymentIdentity) = rpc.startFlow(::CashPaymentFlow, 100.DOLLARS, bobNode.legalIdentity).returnValue.getOrThrow()
val (_, paymentIdentity) = rpc.startFlow(::CashPaymentFlow, 100.DOLLARS, bobNode.chooseIdentity()).returnValue.getOrThrow()
var issueSmId: StateMachineRunId? = null
var moveSmId: StateMachineRunId? = null
@ -167,7 +167,7 @@ class NodeMonitorModelTest : DriverBasedTest() {
// MOVE
expect { add: StateMachineUpdate.Added ->
val initiator = add.stateMachineInfo.initiator
require(initiator is FlowInitiator.Peer && initiator.party.name == aliceNode.legalIdentity.name)
require(initiator is FlowInitiator.Peer && initiator.party.name == aliceNode.chooseIdentity().name)
}
)
}
@ -180,7 +180,7 @@ class NodeMonitorModelTest : DriverBasedTest() {
require(stx.tx.outputs.size == 1)
val signaturePubKeys = stx.sigs.map { it.by }.toSet()
// Only Alice signed
val aliceKey = aliceNode.legalIdentity.owningKey
val aliceKey = aliceNode.chooseIdentity().owningKey
require(signaturePubKeys.size <= aliceKey.keys.size)
require(aliceKey.isFulfilledBy(signaturePubKeys))
issueTx = stx

View File

@ -38,7 +38,8 @@ class NetworkIdentityModel {
val parties: ObservableList<NodeInfo> = networkIdentities.filtered { !it.isCordaService() }
val notaries: ObservableList<NodeInfo> = networkIdentities.filtered { it.advertisedServices.any { it.info.type.isNotary() } }
val myIdentity = rpcProxy.map { it?.nodeIdentity() }
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?
@ -46,4 +47,11 @@ class NetworkIdentityModel {
}
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)
// }
}

View File

@ -15,6 +15,7 @@ import net.corda.node.internal.Node;
import net.corda.node.internal.StartedNode;
import net.corda.node.services.transactions.ValidatingNotaryService;
import net.corda.nodeapi.User;
import net.corda.testing.CoreTestUtils;
import net.corda.testing.node.NodeBasedTest;
import org.junit.After;
import org.junit.Before;
@ -74,7 +75,7 @@ public class CordaRPCJavaClientTest extends NodeBasedTest {
FlowHandle<AbstractCashFlow.Result> flowHandle = rpcProxy.startFlowDynamic(CashIssueFlow.class,
DOLLARS(123), OpaqueBytes.of("1".getBytes()),
node.getInfo().getLegalIdentity());
CoreTestUtils.chooseIdentity(node.getInfo()));
System.out.println("Started issuing cash, waiting on result");
flowHandle.getReturnValue().get();

View File

@ -20,6 +20,7 @@ import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
import net.corda.node.services.transactions.ValidatingNotaryService
import net.corda.nodeapi.User
import net.corda.testing.ALICE
import net.corda.testing.chooseIdentity
import net.corda.testing.node.NodeBasedTest
import org.apache.activemq.artemis.api.core.ActiveMQSecurityException
import org.assertj.core.api.Assertions.assertThatExceptionOfType
@ -81,7 +82,7 @@ class CordaRPCClientTest : NodeBasedTest() {
println("Creating proxy")
println("Starting flow")
val flowHandle = connection!!.proxy.startTrackedFlow(::CashIssueFlow,
20.DOLLARS, OpaqueBytes.of(0), node.info.legalIdentity
20.DOLLARS, OpaqueBytes.of(0), node.info.chooseIdentity()
)
println("Started flow, waiting on result")
flowHandle.progress.subscribe {
@ -93,7 +94,7 @@ class CordaRPCClientTest : NodeBasedTest() {
@Test
fun `sub-type of FlowException thrown by flow`() {
login(rpcUser.username, rpcUser.password)
val handle = connection!!.proxy.startFlow(::CashPaymentFlow, 100.DOLLARS, node.info.legalIdentity)
val handle = connection!!.proxy.startFlow(::CashPaymentFlow, 100.DOLLARS, node.info.chooseIdentity())
assertThatExceptionOfType(CashException::class.java).isThrownBy {
handle.returnValue.getOrThrow()
}
@ -102,7 +103,7 @@ class CordaRPCClientTest : NodeBasedTest() {
@Test
fun `check basic flow has no progress`() {
login(rpcUser.username, rpcUser.password)
connection!!.proxy.startFlow(::CashPaymentFlow, 100.DOLLARS, node.info.legalIdentity).use {
connection!!.proxy.startFlow(::CashPaymentFlow, 100.DOLLARS, node.info.chooseIdentity()).use {
assertFalse(it is FlowProgressHandle<*>)
assertTrue(it is FlowHandle<*>)
}
@ -116,7 +117,7 @@ class CordaRPCClientTest : NodeBasedTest() {
assertTrue(startCash.isEmpty(), "Should not start with any cash")
val flowHandle = proxy.startFlow(::CashIssueFlow,
123.DOLLARS, OpaqueBytes.of(0), node.info.legalIdentity
123.DOLLARS, OpaqueBytes.of(0), node.info.chooseIdentity()
)
println("Started issuing cash, waiting on result")
flowHandle.returnValue.get()
@ -141,7 +142,7 @@ class CordaRPCClientTest : NodeBasedTest() {
countShellFlows++
}
}
val nodeIdentity = node.info.legalIdentity
val nodeIdentity = node.info.chooseIdentity()
node.services.startFlow(CashIssueFlow(2000.DOLLARS, OpaqueBytes.of(0), nodeIdentity), FlowInitiator.Shell).resultFuture.getOrThrow()
proxy.startFlow(::CashIssueFlow,
123.DOLLARS,

View File

@ -3,6 +3,7 @@ package net.corda.java.rpc;
import net.corda.client.rpc.CordaRPCConnection;
import net.corda.core.contracts.Amount;
import net.corda.core.identity.CordaX500Name;
import net.corda.core.identity.Party;
import net.corda.core.messaging.CordaRPCOps;
import net.corda.core.messaging.FlowHandle;
import net.corda.core.node.NodeInfo;
@ -41,6 +42,7 @@ public class StandaloneCordaRPCJavaClientTest {
private CordaRPCOps rpcProxy;
private CordaRPCConnection connection;
private NodeInfo notaryNode;
private Party notaryNodeIdentity;
private NodeConfig notaryConfig = new NodeConfig(
new CordaX500Name("Notary Service", "Zurich", "CH"),
@ -60,6 +62,7 @@ public class StandaloneCordaRPCJavaClientTest {
connection = notary.connect();
rpcProxy = connection.getProxy();
notaryNode = fetchNotaryIdentity();
notaryNodeIdentity = rpcProxy.nodeInfo().getLegalIdentities().get(0);
}
@After
@ -106,7 +109,7 @@ public class StandaloneCordaRPCJavaClientTest {
FlowHandle<AbstractCashFlow.Result> flowHandle = rpcProxy.startFlowDynamic(CashIssueFlow.class,
dollars123, OpaqueBytes.of("1".getBytes()),
notaryNode.getLegalIdentity());
notaryNodeIdentity);
System.out.println("Started issuing cash, waiting on result");
flowHandle.getReturnValue().get();

View File

@ -5,6 +5,7 @@ import com.google.common.hash.HashingInputStream
import net.corda.client.rpc.CordaRPCConnection
import net.corda.core.crypto.SecureHash
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.internal.*
import net.corda.core.messaging.*
import net.corda.core.node.NodeInfo
@ -56,6 +57,7 @@ class StandaloneCordaRPClientTest {
private lateinit var rpcProxy: CordaRPCOps
private lateinit var connection: CordaRPCConnection
private lateinit var notaryNode: NodeInfo
private lateinit var notaryNodeIdentity: Party
private val notaryConfig = NodeConfig(
legalName = CordaX500Name(organisation = "Notary Service", locality = "Zurich", country = "CH"),
@ -74,6 +76,7 @@ class StandaloneCordaRPClientTest {
connection = notary.connect()
rpcProxy = connection.proxy
notaryNode = fetchNotaryIdentity()
notaryNodeIdentity = rpcProxy.nodeInfo().legalIdentitiesAndCerts.first().party
}
@After
@ -110,7 +113,7 @@ class StandaloneCordaRPClientTest {
@Test
fun `test starting flow`() {
rpcProxy.startFlow(::CashIssueFlow, 127.POUNDS, OpaqueBytes.of(0), notaryNode.notaryIdentity)
rpcProxy.startFlow(::CashIssueFlow, 127.POUNDS, OpaqueBytes.of(0), notaryNodeIdentity)
.returnValue.getOrThrow(timeout)
}
@ -118,7 +121,7 @@ class StandaloneCordaRPClientTest {
fun `test starting tracked flow`() {
var trackCount = 0
val handle = rpcProxy.startTrackedFlow(
::CashIssueFlow, 429.DOLLARS, OpaqueBytes.of(0), notaryNode.notaryIdentity
::CashIssueFlow, 429.DOLLARS, OpaqueBytes.of(0), notaryNodeIdentity
)
val updateLatch = CountDownLatch(1)
handle.progress.subscribe { msg ->
@ -133,7 +136,7 @@ class StandaloneCordaRPClientTest {
@Test
fun `test network map`() {
assertEquals(notaryConfig.legalName, notaryNode.legalIdentity.name)
assertEquals(notaryConfig.legalName, notaryNodeIdentity.name)
}
@Test
@ -152,7 +155,7 @@ class StandaloneCordaRPClientTest {
}
// Now issue some cash
rpcProxy.startFlow(::CashIssueFlow, 513.SWISS_FRANCS, OpaqueBytes.of(0), notaryNode.notaryIdentity)
rpcProxy.startFlow(::CashIssueFlow, 513.SWISS_FRANCS, OpaqueBytes.of(0), notaryNodeIdentity)
.returnValue.getOrThrow(timeout)
updateLatch.await()
assertEquals(1, updateCount.get())
@ -170,7 +173,7 @@ class StandaloneCordaRPClientTest {
}
// Now issue some cash
rpcProxy.startFlow(::CashIssueFlow, 629.POUNDS, OpaqueBytes.of(0), notaryNode.notaryIdentity)
rpcProxy.startFlow(::CashIssueFlow, 629.POUNDS, OpaqueBytes.of(0), notaryNodeIdentity)
.returnValue.getOrThrow(timeout)
updateLatch.await()
@ -184,7 +187,7 @@ class StandaloneCordaRPClientTest {
@Test
fun `test vault query by`() {
// Now issue some cash
rpcProxy.startFlow(::CashIssueFlow, 629.POUNDS, OpaqueBytes.of(0), notaryNode.notaryIdentity)
rpcProxy.startFlow(::CashIssueFlow, 629.POUNDS, OpaqueBytes.of(0), notaryNodeIdentity)
.returnValue.getOrThrow(timeout)
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)
@ -195,7 +198,7 @@ class StandaloneCordaRPClientTest {
assertEquals(1, queryResults.totalStatesAvailable)
assertEquals(queryResults.states.first().state.data.amount.quantity, 629.POUNDS.quantity)
rpcProxy.startFlow(::CashPaymentFlow, 100.POUNDS, notaryNode.legalIdentity).returnValue.getOrThrow()
rpcProxy.startFlow(::CashPaymentFlow, 100.POUNDS, notaryNodeIdentity).returnValue.getOrThrow()
val moreResults = rpcProxy.vaultQueryBy<Cash.State>(criteria, paging, sorting)
assertEquals(3, moreResults.totalStatesAvailable) // 629 - 100 + 100
@ -213,7 +216,7 @@ class StandaloneCordaRPClientTest {
println(startCash)
assertTrue(startCash.isEmpty(), "Should not start with any cash")
val flowHandle = rpcProxy.startFlow(::CashIssueFlow, 629.DOLLARS, OpaqueBytes.of(0), notaryNode.legalIdentity)
val flowHandle = rpcProxy.startFlow(::CashIssueFlow, 629.DOLLARS, OpaqueBytes.of(0), notaryNodeIdentity)
println("Started issuing cash, waiting on result")
flowHandle.returnValue.get()

View File

@ -96,10 +96,10 @@ abstract class AbstractStateReplacementFlow {
@Suspendable
private fun collectSignatures(participants: Iterable<PublicKey>, stx: SignedTransaction): List<TransactionSignature> {
// In identity service we record all identities we know about from network map.
val parties = participants.map {
val participantNode = serviceHub.networkMapCache.getNodeByLegalIdentityKey(it) ?:
serviceHub.identityService.partyFromKey(it) ?:
throw IllegalStateException("Participant $it to state $originalState not found on the network")
participantNode.legalIdentity
}
val participantSignatures = parties.map { getParticipantSignature(it, stx) }
@ -193,7 +193,8 @@ abstract class AbstractStateReplacementFlow {
private fun checkMySignatureRequired(stx: SignedTransaction) {
// TODO: use keys from the keyManagementService instead
val myKey = serviceHub.myInfo.legalIdentity.owningKey
// TODO Check the set of multiple identities?
val myKey = ourIdentity.owningKey
val requiredKeys = if (stx.isNotaryChangeTransaction()) {
stx.resolveNotaryChangeTransaction(serviceHub).requiredSigningKeys

View File

@ -20,7 +20,7 @@ class BroadcastTransactionFlow(val notarisedTransaction: SignedTransaction,
@Suspendable
override fun call() {
// TODO: Messaging layer should handle this broadcast for us
participants.filter { it != serviceHub.myInfo.legalIdentity }.forEach { participant ->
participants.filter { it !in serviceHub.myInfo.legalIdentities }.forEach { participant ->
// SendTransactionFlow allows otherParty to access our data to resolve the transaction.
subFlow(SendTransactionFlow(participant, notarisedTransaction))
}

View File

@ -77,7 +77,7 @@ class CollectSignaturesFlow @JvmOverloads constructor (val partiallySignedTx: Si
@Suspendable override fun call(): SignedTransaction {
// Check the signatures which have already been provided and that the transaction is valid.
// Usually just the Initiator and possibly an oracle would have signed at this point.
val myKeys: Iterable<PublicKey> = myOptionalKeys ?: listOf(serviceHub.myInfo.legalIdentity.owningKey)
val myKeys: Iterable<PublicKey> = myOptionalKeys ?: listOf(ourIdentity.owningKey)
val signed = partiallySignedTx.sigs.map { it.by }
val notSigned = partiallySignedTx.tx.requiredSigningKeys - signed
@ -112,7 +112,7 @@ class CollectSignaturesFlow @JvmOverloads constructor (val partiallySignedTx: Si
}
/**
* Lookup the [Party] object for each [PublicKey] using the [ServiceHub.networkMapCache].
* Lookup the [Party] object for each [PublicKey] using the [ServiceHub.identityService].
*
* @return a pair of the well known identity to contact for a signature, and the public key that party should sign
* with (this may belong to a confidential identity).

View File

@ -53,8 +53,6 @@ open class FinalityFlow(val transactions: Iterable<SignedTransaction>,
fun tracker() = ProgressTracker(NOTARISING, BROADCASTING)
}
open protected val ourIdentity: Party get() = serviceHub.myInfo.legalIdentity
@Suspendable
@Throws(NotaryException::class)
override fun call(): List<SignedTransaction> {
@ -70,7 +68,7 @@ open class FinalityFlow(val transactions: Iterable<SignedTransaction>,
// Each transaction has its own set of recipients, but extra recipients get them all.
progressTracker.currentStep = BROADCASTING
for ((stx, parties) in notarisedTxns) {
val participants = (parties + extraRecipients).filter { it != ourIdentity }.toSet()
val participants = (parties + extraRecipients).filter { it != ourIdentity.party }.toSet()
if (participants.isNotEmpty()) {
broadcastTransaction(stx, participants.toNonEmptySet())
}

View File

@ -3,6 +3,7 @@ package net.corda.core.flows
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.crypto.SecureHash
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.abbreviate
import net.corda.core.messaging.DataFeed
@ -56,6 +57,12 @@ abstract class FlowLogic<out T> {
@Suspendable
fun initiateFlow(party: Party): FlowSession = stateMachine.initiateFlow(party, flowUsedForSessions)
/**
* Specifies our identity in the flow. With node's multiple identities we can choose which one to use for communication.
* Defaults to the first one from [NodeInfo.legalIdentitiesAndCerts].
*/
val ourIdentity: PartyAndCertificate get() = stateMachine.ourIdentity
/**
* Returns a [FlowInfo] object describing the flow [otherParty] is using. With [FlowInfo.flowVersion] it
* provides the necessary information needed for the evolution of flows and enabling backwards compatibility.

View File

@ -39,7 +39,7 @@ object IdentitySyncFlow {
val identities: Set<AbstractParty> = states.flatMap { it.participants }.toSet()
// Filter participants down to the set of those not in the network map (are not well known)
val confidentialIdentities = identities
.filter { serviceHub.networkMapCache.getNodeByLegalIdentityKey(it.owningKey) == null }
.filter { serviceHub.networkMapCache.getNodesByLegalIdentityKey(it.owningKey).isEmpty() }
.toList()
val identityCertificates: Map<AbstractParty, PartyAndCertificate?> = identities
.map { Pair(it, serviceHub.identityService.certificateFromKey(it.owningKey)) }.toMap()

View File

@ -36,17 +36,17 @@ class SwapIdentitiesFlow(val otherSide: Party,
@Suspendable
override fun call(): LinkedHashMap<Party, AnonymousParty> {
progressTracker.currentStep = AWAITING_KEY
val legalIdentityAnonymous = serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.legalIdentityAndCert, revocationEnabled)
val legalIdentityAnonymous = serviceHub.keyManagementService.freshKeyAndCert(ourIdentity, revocationEnabled)
// Special case that if we're both parties, a single identity is generated
val identities = LinkedHashMap<Party, AnonymousParty>()
if (otherSide == serviceHub.myInfo.legalIdentity) {
if (otherSide in serviceHub.myInfo.legalIdentities) {
identities.put(otherSide, legalIdentityAnonymous.party.anonymise())
} else {
val anonymousOtherSide = sendAndReceive<PartyAndCertificate>(otherSide, legalIdentityAnonymous).unwrap { confidentialIdentity ->
validateAndRegisterIdentity(serviceHub.identityService, otherSide, confidentialIdentity)
}
identities.put(serviceHub.myInfo.legalIdentity, legalIdentityAnonymous.party.anonymise())
identities.put(ourIdentity.party, legalIdentityAnonymous.party.anonymise())
identities.put(otherSide, anonymousOtherSide.party.anonymise())
}
return identities

View File

@ -5,6 +5,7 @@ import net.corda.core.concurrent.CordaFuture
import net.corda.core.crypto.SecureHash
import net.corda.core.flows.*
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.ServiceHub
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.UntrustworthyData
@ -49,4 +50,5 @@ interface FlowStateMachine<R> {
val id: StateMachineRunId
val resultFuture: CordaFuture<R>
val flowInitiator: FlowInitiator
val ourIdentity: PartyAndCertificate
}

View File

@ -56,7 +56,7 @@ interface CordaRPCOps : RPCOps {
* Returns the RPC protocol version, which is the same the node's Platform Version. Exists since version 1 so guaranteed
* to be present.
*/
override val protocolVersion: Int get() = nodeIdentity().platformVersion
override val protocolVersion: Int get() = nodeInfo().platformVersion
/**
* Returns a list of currently in-progress state machine infos.
@ -208,9 +208,9 @@ interface CordaRPCOps : RPCOps {
fun <T> startTrackedFlowDynamic(logicType: Class<out FlowLogic<T>>, vararg args: Any?): FlowProgressHandle<T>
/**
* Returns Node's identity, assuming this will not change while the node is running.
* Returns Node's NodeInfo, assuming this will not change while the node is running.
*/
fun nodeIdentity(): NodeInfo
fun nodeInfo(): NodeInfo
/*
* Add note(s) to an existing Vault transaction

View File

@ -18,22 +18,20 @@ data class ServiceEntry(val info: ServiceInfo, val identity: PartyAndCertificate
* Info about a network node that acts on behalf of some form of contract party.
*/
// TODO We currently don't support multi-IP/multi-identity nodes, we only left slots in the data structures.
// Note that order of `legalIdentitiesAndCerts` is now important. We still treat the first identity as a special one.
// It will change after introducing proper multi-identity management.
@CordaSerializable
data class NodeInfo(val addresses: List<NetworkHostAndPort>,
// TODO After removing of services these two fields will be merged together and made NonEmptySet.
val legalIdentityAndCert: PartyAndCertificate,
val legalIdentitiesAndCerts: Set<PartyAndCertificate>,
val legalIdentitiesAndCerts: List<PartyAndCertificate>,
val platformVersion: Int,
val advertisedServices: List<ServiceEntry> = emptyList(),
val serial: Long
) {
init {
require(advertisedServices.none { it.identity == legalIdentityAndCert }) {
"Service identities must be different from node legal identity"
}
require(legalIdentitiesAndCerts.isNotEmpty()) { "Node should have at least one legal identity" }
}
val legalIdentity: Party get() = legalIdentityAndCert.party
// TODO This part will be removed with services removal.
val notaryIdentity: Party get() = advertisedServices.single { it.info.type.isNotary() }.identity.party
fun serviceIdentities(type: ServiceType): List<Party> {
return advertisedServices.mapNotNull { if (it.info.type.isSubTypeOf(type)) it.identity.party else null }
@ -43,7 +41,9 @@ data class NodeInfo(val addresses: List<NetworkHostAndPort>,
* Uses node's owner X500 name to infer the node's location. Used in Explorer in map view.
*/
fun getWorldMapLocation(): WorldMapLocation? {
val nodeOwnerLocation = legalIdentity.name.locality
val nodeOwnerLocation = legalIdentitiesAndCerts.first().name.locality
return nodeOwnerLocation.let { CityDatabase[it] }
}
val legalIdentities: List<Party>
get() = legalIdentitiesAndCerts.map { it.party }
}

View File

@ -5,6 +5,8 @@ import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SignableData
import net.corda.core.crypto.SignatureMetadata
import net.corda.core.crypto.TransactionSignature
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.services.*
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.transactions.FilteredTransaction
@ -129,16 +131,7 @@ interface ServiceHub : ServicesForResolution {
}
}
/**
* Helper property to shorten code for fetching the the [PublicKey] portion of the
* Node's primary signing identity.
* Typical use is during signing in flows and for unit test signing.
* When this [PublicKey] is passed into the signing methods below, or on the KeyManagementService
* the matching [java.security.PrivateKey] will be looked up internally and used to sign.
* If the key is actually a CompositeKey, the first leaf key hosted on this node
* will be used to create the signature.
*/
val legalIdentityKey: PublicKey get() = this.myInfo.legalIdentity.owningKey
private val legalIdentityKey: PublicKey get() = this.myInfo.legalIdentitiesAndCerts.first().owningKey
/**
* Helper property to shorten code for fetching the the [PublicKey] portion of the
@ -288,4 +281,4 @@ interface ServiceHub : ServicesForResolution {
* @return A new [Connection]
*/
fun jdbcSession(): Connection
}
}

View File

@ -8,6 +8,7 @@ import net.corda.core.identity.Party
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
@ -58,6 +59,14 @@ interface NetworkMapCache {
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,
@ -82,14 +91,17 @@ interface NetworkMapCache {
/** 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
}
/**
* 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 info for a specific peer key. */
fun getNodeByLegalIdentityKey(identityKey: PublicKey): NodeInfo?
/** 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> {

View File

@ -1,21 +1,13 @@
package net.corda.core.node.services
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.NodeInfo
import net.corda.core.node.ServiceEntry
import net.corda.core.utilities.NetworkHostAndPort
/**
* Holds information about a [Party], which may refer to either a specific node or a service.
*/
sealed class PartyInfo {
abstract val party: PartyAndCertificate
data class Node(val node: NodeInfo) : PartyInfo() {
override val party get() = node.legalIdentityAndCert
}
data class Service(val service: ServiceEntry) : PartyInfo() {
override val party get() = service.identity
}
}
abstract val party: Party
data class SingleNode(override val party: Party, val addresses: List<NetworkHostAndPort>): PartyInfo()
data class DistributedNode(override val party: Party): PartyInfo()
}

View File

@ -34,7 +34,7 @@ object NodeInfoSchemaV1 : MappedSchema(
@JoinTable(name = "link_nodeinfo_party",
joinColumns = arrayOf(JoinColumn(name="node_info_id")),
inverseJoinColumns = arrayOf(JoinColumn(name="party_name")))
val legalIdentitiesAndCerts: Set<DBPartyAndCertificate>,
val legalIdentitiesAndCerts: List<DBPartyAndCertificate>,
@Column(name = "platform_version")
val platformVersion: Int,
@ -54,8 +54,7 @@ object NodeInfoSchemaV1 : MappedSchema(
fun toNodeInfo(): NodeInfo {
return NodeInfo(
this.addresses.map { it.toHostAndPort() },
this.legalIdentitiesAndCerts.filter { it.isMain }.single().toLegalIdentityAndCert(), // TODO Workaround, it will be changed after PR with services removal.
this.legalIdentitiesAndCerts.filter { !it.isMain }.map { it.toLegalIdentityAndCert() }.toSet(),
(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")

View File

@ -4,6 +4,7 @@ import co.paralleluniverse.fibers.Suspendable;
import com.google.common.primitives.Primitives;
import net.corda.core.identity.Party;
import net.corda.node.internal.StartedNode;
import net.corda.testing.CoreTestUtils;
import net.corda.testing.node.MockNetwork;
import org.junit.After;
import org.junit.Before;
@ -39,7 +40,7 @@ public class FlowsInJavaTest {
@Test
public void suspendableActionInsideUnwrap() throws Exception {
node2.getInternals().registerInitiatedFlow(SendHelloAndThenReceive.class);
Future<String> result = node1.getServices().startFlow(new SendInUnwrapFlow(node2.getInfo().getLegalIdentity())).getResultFuture();
Future<String> result = node1.getServices().startFlow(new SendInUnwrapFlow(CoreTestUtils.chooseIdentity(node2.getInfo()))).getResultFuture();
mockNet.runNetwork();
assertThat(result.get()).isEqualTo("Hello");
}
@ -54,7 +55,7 @@ public class FlowsInJavaTest {
}
private void primitiveReceiveTypeTest(Class<?> receiveType) throws InterruptedException {
PrimitiveReceiveFlow flow = new PrimitiveReceiveFlow(node2.getInfo().getLegalIdentity(), receiveType);
PrimitiveReceiveFlow flow = new PrimitiveReceiveFlow(CoreTestUtils.chooseIdentity(node2.getInfo()), receiveType);
Future<?> result = node1.getServices().startFlow(flow).getResultFuture();
mockNet.runNetwork();
try {

View File

@ -7,6 +7,7 @@ import net.corda.core.transactions.TransactionBuilder
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.TestDependencyInjectionBase
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
import net.corda.testing.node.MockServices
@ -68,8 +69,8 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
tx.addInputState(makeDummyStateAndRef(i.toString()))
tx.addOutputState(makeDummyState(i), DUMMY_PROGRAM_ID)
tx.addOutputState(makeDummyState(i.toString()), DUMMY_PROGRAM_ID)
tx.addCommand(Commands.Cmd1(i), listOf(services.myInfo.legalIdentity.owningKey))
tx.addCommand(Commands.Cmd2(i), listOf(services.myInfo.legalIdentity.owningKey))
tx.addCommand(Commands.Cmd1(i), listOf(services.myInfo.chooseIdentity().owningKey))
tx.addCommand(Commands.Cmd2(i), listOf(services.myInfo.chooseIdentity().owningKey))
}
return tx.toLedgerTransaction(services)
}

View File

@ -16,6 +16,7 @@ import net.corda.node.services.network.NetworkMapService
import net.corda.node.services.persistence.NodeAttachmentService
import net.corda.node.services.transactions.SimpleNotaryService
import net.corda.node.utilities.DatabaseTransactionManager
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork
import org.junit.After
import org.junit.Before
@ -72,7 +73,7 @@ class AttachmentTests {
// Get node one to run a flow to fetch it and insert it.
mockNet.runNetwork()
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.legalIdentity)
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.chooseIdentity())
mockNet.runNetwork()
assertEquals(0, f1.resultFuture.getOrThrow().fromDisk.size)
@ -86,7 +87,7 @@ class AttachmentTests {
// Shut down node zero and ensure node one can still resolve the attachment.
n0.dispose()
val response: FetchDataFlow.Result<Attachment> = n1.startAttachmentFlow(setOf(id), n0.info.legalIdentity).resultFuture.getOrThrow()
val response: FetchDataFlow.Result<Attachment> = n1.startAttachmentFlow(setOf(id), n0.info.chooseIdentity()).resultFuture.getOrThrow()
assertEquals(attachment, response.fromDisk[0])
}
@ -106,7 +107,7 @@ class AttachmentTests {
// Get node one to fetch a non-existent attachment.
val hash = SecureHash.randomSHA256()
mockNet.runNetwork()
val f1 = n1.startAttachmentFlow(setOf(hash), n0.info.legalIdentity)
val f1 = n1.startAttachmentFlow(setOf(hash), n0.info.chooseIdentity())
mockNet.runNetwork()
val e = assertFailsWith<FetchDataFlow.HashNotFound> { f1.resultFuture.getOrThrow() }
assertEquals(hash, e.requested)
@ -151,7 +152,7 @@ class AttachmentTests {
// Get n1 to fetch the attachment. Should receive corrupted bytes.
mockNet.runNetwork()
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.legalIdentity)
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.chooseIdentity())
mockNet.runNetwork()
assertFailsWith<FetchDataFlow.DownloadedVsRequestedDataMismatch> { f1.resultFuture.getOrThrow() }
}

View File

@ -14,6 +14,8 @@ import net.corda.node.internal.StartedNode
import net.corda.testing.MINI_CORP_KEY
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.contracts.DummyContract
import net.corda.testing.chooseIdentity
import net.corda.testing.chooseIdentityAndCert
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockServices
import org.junit.After
@ -54,7 +56,7 @@ class CollectSignaturesFlowTests {
}
// With this flow, the initiators sends an "offer" to the responder, who then initiates the collect signatures flow.
// This flow is a more simplifed version of the "TwoPartyTrade" flow and is a useful example of how both the
// This flow is a more simplified version of the "TwoPartyTrade" flow and is a useful example of how both the
// "collectSignaturesFlow" and "SignTransactionFlow" can be used in practise.
object TestFlow {
@InitiatingFlow
@ -89,7 +91,7 @@ class CollectSignaturesFlowTests {
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
val myInputKeys = state.participants.map { it.owningKey }
val myKeys = myInputKeys + (identities[serviceHub.myInfo.legalIdentity] ?: serviceHub.myInfo.legalIdentity).owningKey
val myKeys = myInputKeys + (identities[serviceHub.myInfo.chooseIdentity()] ?: serviceHub.myInfo.chooseIdentity()).owningKey
val command = Command(DummyContract.Commands.Create(), myInputKeys)
val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), command)
val ptx = serviceHub.signInitialTransaction(builder)
@ -145,7 +147,7 @@ class CollectSignaturesFlowTests {
@Test
fun `successfully collects two signatures`() {
val bConfidentialIdentity = b.database.transaction {
b.services.keyManagementService.freshKeyAndCert(b.info.legalIdentityAndCert, false)
b.services.keyManagementService.freshKeyAndCert(b.info.chooseIdentityAndCert(), false)
}
a.database.transaction {
// Normally this is handled by TransactionKeyFlow, but here we have to manually let A know about the identity
@ -153,7 +155,7 @@ class CollectSignaturesFlowTests {
}
registerFlowOnAllNodes(TestFlowTwo.Responder::class)
val magicNumber = 1337
val parties = listOf(a.info.legalIdentity, bConfidentialIdentity.party, c.info.legalIdentity)
val parties = listOf(a.info.chooseIdentity(), bConfidentialIdentity.party, c.info.chooseIdentity())
val state = DummyContract.MultiOwnerState(magicNumber, parties)
val flow = a.services.startFlow(TestFlowTwo.Initiator(state))
mockNet.runNetwork()
@ -165,7 +167,7 @@ class CollectSignaturesFlowTests {
@Test
fun `no need to collect any signatures`() {
val onePartyDummyContract = DummyContract.generateInitial(1337, notary, a.info.legalIdentity.ref(1))
val onePartyDummyContract = DummyContract.generateInitial(1337, notary, a.info.chooseIdentity().ref(1))
val ptx = a.services.signInitialTransaction(onePartyDummyContract)
val flow = a.services.startFlow(CollectSignaturesFlow(ptx))
mockNet.runNetwork()
@ -177,7 +179,7 @@ class CollectSignaturesFlowTests {
@Test
fun `fails when not signed by initiator`() {
val onePartyDummyContract = DummyContract.generateInitial(1337, notary, a.info.legalIdentity.ref(1))
val onePartyDummyContract = DummyContract.generateInitial(1337, notary, a.info.chooseIdentity().ref(1))
val miniCorpServices = MockServices(MINI_CORP_KEY)
val ptx = miniCorpServices.signInitialTransaction(onePartyDummyContract)
val flow = a.services.startFlow(CollectSignaturesFlow(ptx))
@ -190,9 +192,9 @@ class CollectSignaturesFlowTests {
@Test
fun `passes with multiple initial signatures`() {
val twoPartyDummyContract = DummyContract.generateInitial(1337, notary,
a.info.legalIdentity.ref(1),
b.info.legalIdentity.ref(2),
b.info.legalIdentity.ref(3))
a.info.chooseIdentity().ref(1),
b.info.chooseIdentity().ref(2),
b.info.chooseIdentity().ref(3))
val signedByA = a.services.signInitialTransaction(twoPartyDummyContract)
val signedByBoth = b.services.addSignature(signedByA)
val flow = a.services.startFlow(CollectSignaturesFlow(signedByBoth))
@ -202,4 +204,3 @@ class CollectSignaturesFlowTests {
println(result.sigs)
}
}

View File

@ -22,6 +22,7 @@ import net.corda.node.internal.StartedNode
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
import net.corda.nodeapi.User
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.node.MockNetwork
@ -73,11 +74,11 @@ class ContractUpgradeFlowTest {
@Test
fun `2 parties contract upgrade`() {
// Create dummy contract.
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, a.info.legalIdentity.ref(1), b.info.legalIdentity.ref(1))
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, a.info.chooseIdentity().ref(1), b.info.chooseIdentity().ref(1))
val signedByA = a.services.signInitialTransaction(twoPartyDummyContract)
val stx = b.services.addSignature(signedByA)
a.services.startFlow(FinalityFlow(stx, setOf(a.info.legalIdentity, b.info.legalIdentity)))
a.services.startFlow(FinalityFlow(stx, setOf(a.info.chooseIdentity(), b.info.chooseIdentity())))
mockNet.runNetwork()
val atx = a.database.transaction { a.services.validatedTransactions.getTransaction(stx.id) }
@ -143,7 +144,7 @@ class ContractUpgradeFlowTest {
fun `2 parties contract upgrade using RPC`() {
rpcDriver(initialiseSerialization = false) {
// Create dummy contract.
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, a.info.legalIdentity.ref(1), b.info.legalIdentity.ref(1))
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, a.info.chooseIdentity().ref(1), b.info.chooseIdentity().ref(1))
val signedByA = a.services.signInitialTransaction(twoPartyDummyContract)
val stx = b.services.addSignature(signedByA)
@ -156,7 +157,7 @@ class ContractUpgradeFlowTest {
))
val rpcA = startProxy(a, user)
val rpcB = startProxy(b, user)
val handle = rpcA.startFlow(::FinalityInvoker, stx, setOf(a.info.legalIdentity, b.info.legalIdentity))
val handle = rpcA.startFlow(::FinalityInvoker, stx, setOf(a.info.chooseIdentity(), b.info.chooseIdentity()))
mockNet.runNetwork()
handle.returnValue.getOrThrow()
@ -218,6 +219,7 @@ class ContractUpgradeFlowTest {
@Test
fun `upgrade Cash to v2`() {
// Create some cash.
val chosenIdentity = a.info.chooseIdentity()
val result = a.services.startFlow(CashIssueFlow(Amount(1000, USD), OpaqueBytes.of(1), notary)).resultFuture
mockNet.runNetwork()
val stx = result.getOrThrow().stx
@ -232,7 +234,7 @@ class ContractUpgradeFlowTest {
// Get contract state from the vault.
val firstState = a.database.transaction { a.services.vaultQueryService.queryBy<ContractState>().states.single() }
assertTrue(firstState.state.data is CashV2.State, "Contract state is upgraded to the new version.")
assertEquals(Amount(1000000, USD).`issued by`(a.info.legalIdentity.ref(1)), (firstState.state.data as CashV2.State).amount, "Upgraded cash contain the correct amount.")
assertEquals(Amount(1000000, USD).`issued by`(chosenIdentity.ref(1)), (firstState.state.data as CashV2.State).amount, "Upgraded cash contain the correct amount.")
assertEquals<Collection<AbstractParty>>(listOf(anonymisedRecipient), (firstState.state.data as CashV2.State).owners, "Upgraded cash belongs to the right owner.")
}

View File

@ -9,6 +9,7 @@ import net.corda.finance.GBP
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.node.MockNetwork
import net.corda.testing.node.MockServices
import org.junit.After
@ -42,9 +43,9 @@ class FinalityFlowTests {
@Test
fun `finalise a simple transaction`() {
val amount = Amount(1000, Issued(nodeA.info.legalIdentity.ref(0), GBP))
val amount = Amount(1000, Issued(nodeA.info.chooseIdentity().ref(0), GBP))
val builder = TransactionBuilder(notary)
Cash().generateIssue(builder, amount, nodeB.info.legalIdentity, notary)
Cash().generateIssue(builder, amount, nodeB.info.chooseIdentity(), notary)
val stx = nodeA.services.signInitialTransaction(builder)
val flow = nodeA.services.startFlow(FinalityFlow(stx))
mockNet.runNetwork()
@ -59,7 +60,7 @@ class FinalityFlowTests {
@Test
fun `reject a transaction with unknown parties`() {
val amount = Amount(1000, Issued(nodeA.info.legalIdentity.ref(0), GBP))
val amount = Amount(1000, Issued(nodeA.info.chooseIdentity().ref(0), GBP))
val fakeIdentity = ALICE // Alice isn't part of this network, so node A won't recognise them
val builder = TransactionBuilder(notary)
Cash().generateIssue(builder, amount, fakeIdentity, notary)

View File

@ -12,6 +12,7 @@ import net.corda.finance.flows.CashIssueAndPaymentFlow
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.node.MockNetwork
import org.junit.After
import org.junit.Before
@ -39,8 +40,8 @@ class IdentitySyncFlowTests {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val alice: Party = aliceNode.services.myInfo.legalIdentity
val bob: Party = bobNode.services.myInfo.legalIdentity
val alice: Party = aliceNode.services.myInfo.chooseIdentity()
val bob: Party = bobNode.services.myInfo.chooseIdentity()
bobNode.internals.registerInitiatedFlow(Receive::class.java)
// Alice issues then pays some cash to a new confidential identity that Bob doesn't know about

View File

@ -8,6 +8,7 @@ import net.corda.core.utilities.getOrThrow
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.node.MockNetwork
import net.corda.testing.node.MockServices
import org.junit.After
@ -43,11 +44,11 @@ class ManualFinalityFlowTests {
@Test
fun `finalise a simple transaction`() {
val amount = Amount(1000, Issued(nodeA.info.legalIdentity.ref(0), GBP))
val amount = Amount(1000, Issued(nodeA.info.chooseIdentity().ref(0), GBP))
val builder = TransactionBuilder(notary)
Cash().generateIssue(builder, amount, nodeB.info.legalIdentity, notary)
Cash().generateIssue(builder, amount, nodeB.info.chooseIdentity(), notary)
val stx = nodeA.services.signInitialTransaction(builder)
val flow = nodeA.services.startFlow(ManualFinalityFlow(stx, setOf(nodeC.info.legalIdentity)))
val flow = nodeA.services.startFlow(ManualFinalityFlow(stx, setOf(nodeC.info.chooseIdentity())))
mockNet.runNetwork()
val result = flow.resultFuture.getOrThrow()
val notarisedTx = result.single()

View File

@ -7,6 +7,7 @@ import net.corda.core.utilities.getOrThrow
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.node.MockNetwork
import org.junit.Test
import kotlin.test.assertEquals
@ -24,8 +25,9 @@ class SwapIdentitiesFlowTests {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val alice: Party = aliceNode.services.myInfo.legalIdentity
val bob: Party = bobNode.services.myInfo.legalIdentity
val alice: Party = aliceNode.services.myInfo.chooseIdentity()
val bob: Party = bobNode.services.myInfo.chooseIdentity()
mockNet.registerIdentities()
// Run the flows
val requesterFlow = aliceNode.services.startFlow(SwapIdentitiesFlow(bob))

View File

@ -15,6 +15,7 @@ import net.corda.testing.DUMMY_NOTARY_KEY
import net.corda.testing.MEGA_CORP
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.node.MockNetwork
import net.corda.testing.node.MockServices
@ -59,7 +60,7 @@ class ResolveTransactionsFlowTest {
@Test
fun `resolve from two hashes`() {
val (stx1, stx2) = makeTransactions()
val p = TestFlow(setOf(stx2.id), a.info.legalIdentity)
val p = TestFlow(setOf(stx2.id), a.info.chooseIdentity())
val future = b.services.startFlow(p).resultFuture
mockNet.runNetwork()
val results = future.getOrThrow()
@ -74,7 +75,7 @@ class ResolveTransactionsFlowTest {
@Test
fun `dependency with an error`() {
val stx = makeTransactions(signFirstTX = false).second
val p = TestFlow(setOf(stx.id), a.info.legalIdentity)
val p = TestFlow(setOf(stx.id), a.info.chooseIdentity())
val future = b.services.startFlow(p).resultFuture
mockNet.runNetwork()
assertFailsWith(SignedTransaction.SignaturesMissingException::class) { future.getOrThrow() }
@ -83,7 +84,7 @@ class ResolveTransactionsFlowTest {
@Test
fun `resolve from a signed transaction`() {
val (stx1, stx2) = makeTransactions()
val p = TestFlow(stx2, a.info.legalIdentity)
val p = TestFlow(stx2, a.info.chooseIdentity())
val future = b.services.startFlow(p).resultFuture
mockNet.runNetwork()
future.getOrThrow()
@ -108,7 +109,7 @@ class ResolveTransactionsFlowTest {
}
cursor = stx
}
val p = TestFlow(setOf(cursor.id), a.info.legalIdentity, 40)
val p = TestFlow(setOf(cursor.id), a.info.chooseIdentity(), 40)
val future = b.services.startFlow(p).resultFuture
mockNet.runNetwork()
assertFailsWith<ResolveTransactionsFlow.ExcessivelyLargeTransactionGraph> { future.getOrThrow() }
@ -132,7 +133,7 @@ class ResolveTransactionsFlowTest {
a.services.recordTransactions(stx2, stx3)
}
val p = TestFlow(setOf(stx3.id), a.info.legalIdentity)
val p = TestFlow(setOf(stx3.id), a.info.chooseIdentity())
val future = b.services.startFlow(p).resultFuture
mockNet.runNetwork()
future.getOrThrow()
@ -154,7 +155,7 @@ class ResolveTransactionsFlowTest {
a.services.attachments.importAttachment(makeJar())
}
val stx2 = makeTransactions(withAttachment = id).second
val p = TestFlow(stx2, a.info.legalIdentity)
val p = TestFlow(stx2, a.info.chooseIdentity())
val future = b.services.startFlow(p).resultFuture
mockNet.runNetwork()
future.getOrThrow()

View File

@ -19,6 +19,7 @@ import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.network.NetworkMapService
import net.corda.node.services.persistence.NodeAttachmentService
import net.corda.node.utilities.DatabaseTransactionManager
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork
import org.junit.After
import org.junit.Before
@ -96,7 +97,7 @@ class AttachmentSerializationTest {
@InitiatingFlow
private abstract class ClientLogic(server: StartedNode<*>) : FlowLogic<ClientResult>() {
internal val server = server.info.legalIdentity
internal val server = server.info.chooseIdentity()
@Suspendable
internal fun communicate() {

View File

@ -27,5 +27,4 @@ Additional, ``ServiceHub`` exposes the following properties:
* ``ServiceHub.toSignedTransaction`` to sign a ``TransactionBuilder`` and convert it into a ``SignedTransaction``
* ``ServiceHub.createSignature`` and ``ServiceHub.addSignature`` to create and add signatures to a ``SignedTransaction``
Finally, ``ServiceHub`` exposes the node's legal identity key (via ``ServiceHub.legalIdentityKey``) and its notary
identity key (via ``ServiceHub.notaryIdentityKey``).
Finally, ``ServiceHub`` exposes notary identity key via ``ServiceHub.notaryIdentityKey``.

View File

@ -67,7 +67,7 @@ class IntegrationTestingTutorial {
(1..10).map { i ->
aliceProxy.startFlow(::CashPaymentFlow,
i.DOLLARS,
bob.nodeInfo.legalIdentity,
bob.nodeInfo.chooseIdentity(),
true
).returnValue
}.transpose().getOrThrow()
@ -89,7 +89,7 @@ class IntegrationTestingTutorial {
// START 5
for (i in 1..10) {
bobProxy.startFlow(::CashPaymentFlow, i.DOLLARS, alice.nodeInfo.legalIdentity).returnValue.getOrThrow()
bobProxy.startFlow(::CashPaymentFlow, i.DOLLARS, alice.nodeInfo.chooseIdentity()).returnValue.getOrThrow()
}
aliceVaultUpdates.expectEvents {

View File

@ -134,15 +134,14 @@ public class FlowCookbookJava {
// We may also need to identify a specific counterparty.
// Again, we do so using the network map.
// DOCSTART 2
Party namedCounterparty = getServiceHub().getNetworkMapCache().getNodeByLegalName(new CordaX500Name("NodeA", "London", "UK")).getLegalIdentity();
Party keyedCounterparty = getServiceHub().getNetworkMapCache().getNodeByLegalIdentityKey(dummyPubKey).getLegalIdentity();
Party firstCounterparty = getServiceHub().getNetworkMapCache().getPartyNodes().get(0).getLegalIdentity();
Party namedCounterparty = getServiceHub().getIdentityService().partyFromX500Name(new CordaX500Name("NodeA", "London", "UK"));
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().getNodesWithService(ServiceType.Companion.getRegulator()).get(0).getLegalIdentity();
Party regulator = getServiceHub().getNetworkMapCache().getPeersWithService(ServiceType.Companion.getRegulator()).get(0).getIdentity().getParty();
// DOCEND 3
/*------------------------------
@ -267,7 +266,7 @@ public class FlowCookbookJava {
// matching every public key in all of the transaction's commands.
// DOCSTART 24
DummyContract.Commands.Create commandData = new DummyContract.Commands.Create();
PublicKey ourPubKey = getServiceHub().getLegalIdentityKey();
PublicKey ourPubKey = getServiceHub().getMyInfo().getLegalIdentitiesAndCerts().get(0).getOwningKey();
PublicKey counterpartyPubKey = counterparty.getOwningKey();
List<PublicKey> requiredSigners = ImmutableList.of(ourPubKey, counterpartyPubKey);
Command<DummyContract.Commands.Create> ourCommand = new Command<>(commandData, requiredSigners);

View File

@ -113,7 +113,7 @@ fun generateTransactions(proxy: CordaRPCOps) {
val issueRef = OpaqueBytes.of(0)
val parties = proxy.networkMapSnapshot()
val notary = parties.first { it.advertisedServices.any { it.info.type.isNotary() } }.notaryIdentity
val me = proxy.nodeIdentity().legalIdentity
val me = proxy.nodeInfo().legalIdentities.first()
while (true) {
Thread.sleep(1000)
val random = SplittableRandom()

View File

@ -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.chooseIdentity
import java.util.*
// DOCSTART CustomVaultQuery
@ -139,7 +140,7 @@ object TopupIssuerFlow {
val issueTx = subFlow(issueCashFlow)
// NOTE: issueCashFlow performs a Broadcast (which stores a local copy of the txn to the ledger)
// short-circuit when issuing to self
if (issueTo == serviceHub.myInfo.legalIdentity)
if (issueTo == serviceHub.myInfo.chooseIdentity())
return issueTx
// now invoke Cash subflow to Move issued assetType to issue requester
progressTracker.currentStep = TRANSFERRING

View File

@ -112,18 +112,17 @@ object FlowCookbook {
val firstNotary: Party = serviceHub.networkMapCache.notaryNodes[0].notaryIdentity
// DOCEND 1
// We may also need to identify a specific counterparty. Again, we
// do so using the network map.
// We may also need to identify a specific counterparty. We
// do so using identity service.
// DOCSTART 2
val namedCounterparty: Party? = serviceHub.networkMapCache.getNodeByLegalName(CordaX500Name(organisation = "NodeA", locality = "London", country = "UK"))?.legalIdentity
val keyedCounterparty: Party? = serviceHub.networkMapCache.getNodeByLegalIdentityKey(dummyPubKey)?.legalIdentity
val firstCounterparty: Party = serviceHub.networkMapCache.partyNodes[0].legalIdentity
val namedCounterparty: Party? = serviceHub.identityService.partyFromX500Name(CordaX500Name(organisation = "NodeA", locality = "London", country = "UK"))
val keyedCounterparty: Party? = serviceHub.identityService.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
val regulator: Party = serviceHub.networkMapCache.getNodesWithService(ServiceType.regulator)[0].legalIdentity
val regulator: Party = serviceHub.networkMapCache.getPeersWithService(ServiceType.regulator)[0].identity.party
// DOCEND 3
/**-----------------------------
@ -248,7 +247,7 @@ object FlowCookbook {
// matching every public key in all of the transaction's commands.
// DOCSTART 24
val commandData: DummyContract.Commands.Create = DummyContract.Commands.Create()
val ourPubKey: PublicKey = serviceHub.legalIdentityKey
val ourPubKey: PublicKey = serviceHub.myInfo.legalIdentitiesAndCerts.first().owningKey
val counterpartyPubKey: PublicKey = counterparty.owningKey
val requiredSigners: List<PublicKey> = listOf(ourPubKey, counterpartyPubKey)
val ourCommand: Command<DummyContract.Commands.Create> = Command(commandData, requiredSigners)

View File

@ -17,6 +17,7 @@ import net.corda.core.utilities.unwrap
import net.corda.finance.contracts.asset.CASH_PROGRAM_ID
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.schemas.CashSchemaV1
import net.corda.testing.chooseIdentity
import java.util.*
@CordaSerializable
@ -74,7 +75,7 @@ private fun prepareOurInputsAndOutputs(serviceHub: ServiceHub, lockId: UUID, req
val outputs = if (residual > 0L) {
// Build an output state for the residual change back to us
val residualAmount = Amount(residual, sellAmount.token)
val residualOutput = Cash.State(residualAmount, serviceHub.myInfo.legalIdentity)
val residualOutput = Cash.State(residualAmount, serviceHub.myInfo.chooseIdentity())
listOf(transferedFundsOutput, residualOutput)
} else {
listOf(transferedFundsOutput)
@ -96,11 +97,11 @@ class ForeignExchangeFlow(val tradeId: String,
// Select correct sides of the Fx exchange to query for.
// Specifically we own the assets we wish to sell.
// Also prepare the other side query
val (localRequest, remoteRequest) = if (baseCurrencySeller == serviceHub.myInfo.legalIdentity) {
val (localRequest, remoteRequest) = if (baseCurrencySeller == serviceHub.myInfo.chooseIdentity()) {
val local = FxRequest(tradeId, baseCurrencyAmount, baseCurrencySeller, baseCurrencyBuyer)
val remote = FxRequest(tradeId, quoteCurrencyAmount, baseCurrencyBuyer, baseCurrencySeller)
Pair(local, remote)
} else if (baseCurrencyBuyer == serviceHub.myInfo.legalIdentity) {
} else if (baseCurrencyBuyer == serviceHub.myInfo.chooseIdentity()) {
val local = FxRequest(tradeId, quoteCurrencyAmount, baseCurrencyBuyer, baseCurrencySeller)
val remote = FxRequest(tradeId, baseCurrencyAmount, baseCurrencySeller, baseCurrencyBuyer)
Pair(local, remote)
@ -132,7 +133,7 @@ class ForeignExchangeFlow(val tradeId: String,
>= remoteRequestWithNotary.amount.quantity) {
"the provided inputs don't provide sufficient funds"
}
require(it.filter { it.owner == serviceHub.myInfo.legalIdentity }.
require(it.filter { it.owner == serviceHub.myInfo.chooseIdentity() }.
map { it.amount.quantity }.sum() == remoteRequestWithNotary.amount.quantity) {
"the provided outputs don't provide the request quantity"
}
@ -205,7 +206,7 @@ class ForeignExchangeRemoteFlow(val source: Party) : FlowLogic<Unit>() {
// the lifecycle of the Fx trades which would be included in the transaction
// Check request is for us
require(serviceHub.myInfo.legalIdentity == it.owner) {
require(serviceHub.myInfo.chooseIdentity() == it.owner) {
"Request does not include the correct counterparty"
}
require(source == it.counterparty) {

View File

@ -17,6 +17,7 @@ import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.seconds
import net.corda.core.utilities.unwrap
import net.corda.testing.chooseIdentity
// Minimal state model of a manual approval process
@CordaSerializable
@ -102,7 +103,7 @@ class SubmitTradeApprovalFlow(val tradeId: String,
// Manufacture an initial state
val tradeProposal = TradeApprovalContract.State(
tradeId,
serviceHub.myInfo.legalIdentity,
serviceHub.myInfo.chooseIdentity(),
counterparty)
// identify a notary. This might also be done external to the flow
val notary = serviceHub.networkMapCache.getAnyNotary()
@ -113,7 +114,7 @@ class SubmitTradeApprovalFlow(val tradeId: String,
// We can automatically sign as there is no untrusted data.
val signedTx = serviceHub.signInitialTransaction(tx)
// Notarise and distribute.
subFlow(FinalityFlow(signedTx, setOf(serviceHub.myInfo.legalIdentity, counterparty)))
subFlow(FinalityFlow(signedTx, setOf(serviceHub.myInfo.chooseIdentity(), counterparty)))
// Return the initial state
return signedTx.tx.outRef<TradeApprovalContract.State>(0)
}
@ -148,7 +149,7 @@ class SubmitCompletionFlow(val ref: StateRef, val verdict: WorkflowState) : Flow
"Input trade not modifiable ${latestRecord.state.data.state}"
}
// Check we are the correct Party to run the protocol. Note they will counter check this too.
require(latestRecord.state.data.counterparty == serviceHub.myInfo.legalIdentity) {
require(latestRecord.state.data.counterparty == serviceHub.myInfo.chooseIdentity()) {
"The counterparty must give the verdict"
}
@ -170,7 +171,7 @@ class SubmitCompletionFlow(val ref: StateRef, val verdict: WorkflowState) : Flow
latestRecord,
StateAndContract(newState, TRADE_APPROVAL_PROGRAM_ID),
Command(TradeApprovalContract.Commands.Completed(),
listOf(serviceHub.myInfo.legalIdentity.owningKey, latestRecord.state.data.source.owningKey)))
listOf(serviceHub.myInfo.chooseIdentity().owningKey, latestRecord.state.data.source.owningKey)))
tx.setTimeWindow(serviceHub.clock.instant(), 60.seconds)
// We can sign this transaction immediately as we have already checked all the fields and the decision
// is ultimately a manual one from the caller.
@ -213,7 +214,7 @@ class RecordCompletionFlow(val source: Party) : FlowLogic<Unit>() {
// First we receive the verdict transaction signed by their single key
val completeTx = receive<SignedTransaction>(source).unwrap {
// Check the transaction is signed apart from our own key and the notary
it.verifySignaturesExcept(serviceHub.myInfo.legalIdentity.owningKey, it.tx.notary!!.owningKey)
it.verifySignaturesExcept(serviceHub.myInfo.chooseIdentity().owningKey, it.tx.notary!!.owningKey)
// Check the transaction data is correctly formed
val ltx = it.toLedgerTransaction(serviceHub, false)
ltx.verify()
@ -224,7 +225,7 @@ class RecordCompletionFlow(val source: Party) : FlowLogic<Unit>() {
// Check the context dependent parts of the transaction as the
// Contract verify method must not use serviceHub queries.
val state = ltx.outRef<TradeApprovalContract.State>(0)
require(state.state.data.source == serviceHub.myInfo.legalIdentity) {
require(state.state.data.source == serviceHub.myInfo.chooseIdentity()) {
"Proposal not one of our original proposals"
}
require(state.state.data.counterparty == source) {

View File

@ -13,6 +13,7 @@ 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.node.MockNetwork
import org.junit.After
import org.junit.Assert
@ -77,9 +78,9 @@ class CustomVaultQueryTest {
private fun topUpCurrencies() {
val flowHandle1 = nodeA.services.startFlow(TopupIssuerFlow.TopupIssuanceRequester(
nodeA.info.legalIdentity,
nodeA.info.chooseIdentity(),
OpaqueBytes.of(0x01),
nodeA.info.legalIdentity,
nodeA.info.chooseIdentity(),
notaryNode.info.notaryIdentity))
flowHandle1.resultFuture.getOrThrow()
}

View File

@ -13,6 +13,7 @@ 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.node.MockNetwork
import org.junit.After
import org.junit.Before
@ -69,10 +70,10 @@ class FxTransactionBuildTutorialTest {
// Now run the actual Fx exchange
val doIt = nodeA.services.startFlow(ForeignExchangeFlow("trade1",
POUNDS(100).issuedBy(nodeB.info.legalIdentity.ref(0x01)),
DOLLARS(200).issuedBy(nodeA.info.legalIdentity.ref(0x01)),
nodeA.info.legalIdentity,
nodeB.info.legalIdentity))
POUNDS(100).issuedBy(nodeB.info.chooseIdentity().ref(0x01)),
DOLLARS(200).issuedBy(nodeA.info.chooseIdentity().ref(0x01)),
nodeA.info.chooseIdentity(),
nodeB.info.chooseIdentity()))
// wait for the flow to finish and the vault updates to be done
doIt.resultFuture.getOrThrow()
// Get the balances when the vault updates

View File

@ -14,6 +14,7 @@ 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.node.MockNetwork
import org.junit.After
import org.junit.Before
@ -55,7 +56,7 @@ class WorkflowTransactionBuildTutorialTest {
// Setup a vault subscriber to wait for successful upload of the proposal to NodeB
val nodeBVaultUpdate = nodeB.services.vaultService.updates.toFuture()
// Kick of the proposal flow
val flow1 = nodeA.services.startFlow(SubmitTradeApprovalFlow("1234", nodeB.info.legalIdentity))
val flow1 = nodeA.services.startFlow(SubmitTradeApprovalFlow("1234", nodeB.info.chooseIdentity()))
// Wait for the flow to finish
val proposalRef = flow1.resultFuture.getOrThrow()
val proposalLinearId = proposalRef.state.data.linearId
@ -71,8 +72,8 @@ class WorkflowTransactionBuildTutorialTest {
// Confirm the state as as expected
assertEquals(WorkflowState.NEW, proposalRef.state.data.state)
assertEquals("1234", proposalRef.state.data.tradeId)
assertEquals(nodeA.info.legalIdentity, proposalRef.state.data.source)
assertEquals(nodeB.info.legalIdentity, proposalRef.state.data.counterparty)
assertEquals(nodeA.info.chooseIdentity(), proposalRef.state.data.source)
assertEquals(nodeB.info.chooseIdentity(), proposalRef.state.data.counterparty)
assertEquals(proposalRef, latestFromA)
assertEquals(proposalRef, latestFromB)
// Setup a vault subscriber to pause until the final update is in NodeA and NodeB
@ -95,8 +96,8 @@ class WorkflowTransactionBuildTutorialTest {
// Confirm the state is as expected
assertEquals(WorkflowState.APPROVED, completedRef.state.data.state)
assertEquals("1234", completedRef.state.data.tradeId)
assertEquals(nodeA.info.legalIdentity, completedRef.state.data.source)
assertEquals(nodeB.info.legalIdentity, completedRef.state.data.counterparty)
assertEquals(nodeA.info.chooseIdentity(), completedRef.state.data.source)
assertEquals(nodeB.info.chooseIdentity(), completedRef.state.data.counterparty)
assertEquals(completedRef, finalFromA)
assertEquals(completedRef, finalFromB)
}

View File

@ -59,8 +59,6 @@ with the following:
/** The flow logic is encapsulated within the call() method. */
@Suspendable
override fun call() {
// We retrieve the required identities from the network map.
val me = serviceHub.myInfo.legalIdentity
val notary = serviceHub.networkMapCache.getAnyNotary()
// We create a transaction builder
@ -124,7 +122,6 @@ with the following:
@Override
public Void call() throws FlowException {
// We retrieve the required identities from the network map.
final Party me = getServiceHub().getMyInfo().getLegalIdentity();
final Party notary = getServiceHub().getNetworkMapCache().getAnyNotary(null);
// We create a transaction builder.

View File

@ -47,7 +47,7 @@ Next we create a state object and assign ourselves as the owner. For this exampl
.. sourcecode:: kotlin
val myIdentity = serviceHub.myInfo.legalIdentity
val myIdentity = serviceHub.chooseIdentity()
val state = DummyContract.SingleOwnerState(magicNumber = 42, owner = myIdentity.owningKey)
Then we add the state as the transaction output along with the relevant command. The state will automatically be assigned
@ -63,7 +63,7 @@ We then sign the transaction, build and record it to our transaction storage:
.. sourcecode:: kotlin
val mySigningKey: PublicKey = serviceHub.legalIdentityKey
val mySigningKey: PublicKey = serviceHub.chooseIdentity().owningKey
val issueTransaction = serviceHub.toSignedTransaction(issueTransaction, mySigningKey)
serviceHub.recordTransactions(issueTransaction)

View File

@ -43,7 +43,7 @@ class CashExitFlow(val amount: Amount<Currency>, val issuerRef: OpaqueBytes, pro
override fun call(): AbstractCashFlow.Result {
progressTracker.currentStep = GENERATING_TX
val builder = TransactionBuilder(notary = null as Party?)
val issuer = serviceHub.myInfo.legalIdentity.ref(issuerRef)
val issuer = ourIdentity.party.ref(issuerRef)
val exitStates = CashSelection.getInstance({serviceHub.jdbcSession().metaData}).unconsumedCashStatesForSpending(serviceHub, amount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference))
val signers = try {
Cash().generateExit(

View File

@ -36,17 +36,15 @@ class CashIssueFlow(val amount: Amount<Currency>,
@Suspendable
override fun call(): AbstractCashFlow.Result {
val issuerCert = serviceHub.myInfo.legalIdentityAndCert
progressTracker.currentStep = GENERATING_TX
val builder = TransactionBuilder(notary)
val issuer = issuerCert.party.ref(issuerBankPartyRef)
val signers = Cash().generateIssue(builder, amount.issuedBy(issuer), issuerCert.party, notary)
val issuer = ourIdentity.party.ref(issuerBankPartyRef)
val signers = Cash().generateIssue(builder, amount.issuedBy(issuer), ourIdentity.party, notary)
progressTracker.currentStep = SIGNING_TX
val tx = serviceHub.signInitialTransaction(builder, signers)
progressTracker.currentStep = FINALISING_TX
subFlow(FinalityFlow(tx))
return Result(tx, issuerCert.party)
return Result(tx, ourIdentity.party)
}
@CordaSerializable

View File

@ -54,7 +54,7 @@ object TwoPartyDealFlow {
@Suspendable override fun call(): SignedTransaction {
progressTracker.currentStep = GENERATING_ID
val txIdentities = subFlow(SwapIdentitiesFlow(otherParty))
val anonymousMe = txIdentities.get(serviceHub.myInfo.legalIdentity) ?: serviceHub.myInfo.legalIdentity.anonymise()
val anonymousMe = txIdentities.get(ourIdentity.party) ?: ourIdentity.party.anonymise()
val anonymousCounterparty = txIdentities.get(otherParty) ?: otherParty.anonymise()
progressTracker.currentStep = SENDING_PROPOSAL
// Make the first message we'll send to kick off the flow.
@ -118,7 +118,7 @@ object TwoPartyDealFlow {
logger.trace { "Got signatures from other party, verifying ... " }
progressTracker.currentStep = RECORDING
val ftx = subFlow(FinalityFlow(stx, setOf(otherParty, serviceHub.myInfo.legalIdentity))).single()
val ftx = subFlow(FinalityFlow(stx, setOf(otherParty, ourIdentity.party))).single()
logger.trace { "Recorded transaction." }
@ -150,7 +150,7 @@ object TwoPartyDealFlow {
val wellKnownOtherParty = serviceHub.identityService.partyFromAnonymous(it.primaryIdentity)
val wellKnownMe = serviceHub.identityService.partyFromAnonymous(it.secondaryIdentity)
require(wellKnownOtherParty == otherParty)
require(wellKnownMe == serviceHub.myInfo.legalIdentity)
require(wellKnownMe == ourIdentity.party)
validateHandshake(it)
}
}
@ -197,7 +197,7 @@ object TwoPartyDealFlow {
// We set the transaction's time-window: it may be that none of the contracts need this!
// But it can't hurt to have one.
ptx.setTimeWindow(serviceHub.clock.instant(), 30.seconds)
return Triple(ptx, arrayListOf(deal.participants.single { it == serviceHub.myInfo.legalIdentity as AbstractParty }.owningKey), emptyList())
return Triple(ptx, arrayListOf(deal.participants.single { it == ourIdentity.party as AbstractParty }.owningKey), emptyList())
}
}
}

View File

@ -63,7 +63,7 @@ object TwoPartyTradeFlow {
val notaryNode: NodeInfo,
val assetToSell: StateAndRef<OwnableState>,
val price: Amount<Currency>,
val me: PartyAndCertificate,
val myParty: PartyAndCertificate, // TODO Left because in tests it's used to pass anonymous party.
override val progressTracker: ProgressTracker = Seller.tracker()) : FlowLogic<SignedTransaction>() {
companion object {
@ -82,7 +82,7 @@ object TwoPartyTradeFlow {
override fun call(): SignedTransaction {
progressTracker.currentStep = AWAITING_PROPOSAL
// Make the first message we'll send to kick off the flow.
val hello = SellerTradeInfo(price, me)
val hello = SellerTradeInfo(price, myParty)
// What we get back from the other side is a transaction that *might* be valid and acceptable to us,
// but we must check it out thoroughly before we sign!
// SendTransactionFlow allows otherParty to access our data to resolve the transaction.
@ -107,7 +107,7 @@ object TwoPartyTradeFlow {
}
}
if (stx.tx.outputStates.sumCashBy(me.party).withoutIssuer() != price)
if (stx.tx.outputStates.sumCashBy(myParty.party).withoutIssuer() != price)
throw FlowException("Transaction is not sending us the right amount of cash")
}
}
@ -161,10 +161,9 @@ object TwoPartyTradeFlow {
// Create the identity we'll be paying to, and send the counterparty proof we own the identity
val buyerAnonymousIdentity = if (anonymous)
serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.legalIdentityAndCert, false)
serviceHub.keyManagementService.freshKeyAndCert(ourIdentity, false)
else
serviceHub.myInfo.legalIdentityAndCert
ourIdentity
// Put together a proposed transaction that performs the trade, and sign it.
progressTracker.currentStep = SIGNING
val (ptx, cashSigningPubKeys) = assembleSharedTX(assetForSale, tradeRequest, buyerAnonymousIdentity)

View File

@ -243,7 +243,7 @@ class CommercialPaperTestsGeneric {
// BigCorp™ issues $10,000 of commercial paper, to mature in 30 days, owned initially by itself.
val faceValue = 10000.DOLLARS `issued by` DUMMY_CASH_ISSUER
val issuance = bigCorpServices.myInfo.legalIdentity.ref(1)
val issuance = bigCorpServices.myInfo.chooseIdentity().ref(1)
val issueBuilder = CommercialPaper().generateIssue(issuance, faceValue, TEST_TX_TIME + 30.days, DUMMY_NOTARY)
issueBuilder.setTimeWindow(TEST_TX_TIME, 30.seconds)
val issuePtx = bigCorpServices.signInitialTransaction(issueBuilder)

View File

@ -7,6 +7,7 @@ import net.corda.finance.DOLLARS
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.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetwork.MockNode
@ -31,7 +32,7 @@ class CashExitFlowTests {
notaryNode = nodes.notaryNode
bankOfCordaNode = nodes.partyNodes[0]
notary = notaryNode.info.notaryIdentity
bankOfCorda = bankOfCordaNode.info.legalIdentity
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
mockNet.runNetwork()
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture

View File

@ -7,6 +7,7 @@ import net.corda.finance.DOLLARS
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.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetwork.MockNode
@ -29,7 +30,7 @@ class CashIssueFlowTests {
notaryNode = nodes.notaryNode
bankOfCordaNode = nodes.partyNodes[0]
notary = notaryNode.info.notaryIdentity
bankOfCorda = bankOfCordaNode.info.legalIdentity
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
mockNet.runNetwork()
}

View File

@ -10,6 +10,7 @@ import net.corda.finance.DOLLARS
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.expect
import net.corda.testing.expectEvents
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
@ -36,7 +37,7 @@ class CashPaymentFlowTests {
notaryNode = nodes.notaryNode
bankOfCordaNode = nodes.partyNodes[0]
notary = notaryNode.info.notaryIdentity
bankOfCorda = bankOfCordaNode.info.legalIdentity
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture
mockNet.runNetwork()
@ -50,7 +51,7 @@ class CashPaymentFlowTests {
@Test
fun `pay some cash`() {
val payTo = notaryNode.info.legalIdentity
val payTo = notaryNode.info.chooseIdentity()
val expectedPayment = 500.DOLLARS
val expectedChange = 1500.DOLLARS
@ -90,7 +91,7 @@ class CashPaymentFlowTests {
@Test
fun `pay more than we have`() {
val payTo = notaryNode.info.legalIdentity
val payTo = notaryNode.info.chooseIdentity()
val expected = 4000.DOLLARS
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected,
payTo)).resultFuture
@ -102,7 +103,7 @@ class CashPaymentFlowTests {
@Test
fun `pay zero cash`() {
val payTo = notaryNode.info.legalIdentity
val payTo = notaryNode.info.chooseIdentity()
val expected = 0.DOLLARS
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected,
payTo)).resultFuture

View File

@ -1,11 +1,11 @@
package net.corda.nodeapi
import net.corda.core.identity.CordaX500Name
import net.corda.core.utilities.toBase58String
import net.corda.core.identity.Party
import net.corda.core.messaging.MessageRecipientGroup
import net.corda.core.messaging.MessageRecipients
import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.node.NodeInfo
import net.corda.core.node.services.ServiceType
import net.corda.core.internal.read
import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SingletonSerializeAsToken
@ -29,8 +29,7 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
const val PEER_USER = "SystemUsers/Peer"
const val INTERNAL_PREFIX = "internal."
const val PEERS_PREFIX = "${INTERNAL_PREFIX}peers."
const val SERVICES_PREFIX = "${INTERNAL_PREFIX}services."
const val PEERS_PREFIX = "${INTERNAL_PREFIX}peers." //TODO Come up with better name for common peers/services queue
const val IP_REQUEST_PREFIX = "ip."
const val P2P_QUEUE = "p2p.inbound"
const val NOTIFICATIONS_ADDRESS = "${INTERNAL_PREFIX}activemq.notifications"
@ -64,13 +63,9 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
@CordaSerializable
data class NodeAddress(override val queueName: String, override val hostAndPort: NetworkHostAndPort) : ArtemisPeerAddress {
companion object {
fun asPeer(peerIdentity: PublicKey, hostAndPort: NetworkHostAndPort): NodeAddress {
fun asSingleNode(peerIdentity: PublicKey, hostAndPort: NetworkHostAndPort): NodeAddress {
return NodeAddress("$PEERS_PREFIX${peerIdentity.toBase58String()}", hostAndPort)
}
fun asService(serviceIdentity: PublicKey, hostAndPort: NetworkHostAndPort): NodeAddress {
return NodeAddress("$SERVICES_PREFIX${serviceIdentity.toBase58String()}", hostAndPort)
}
}
}
@ -84,7 +79,7 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
* @param identity The service identity's owning key.
*/
data class ServiceAddress(val identity: PublicKey) : ArtemisAddress, MessageRecipientGroup {
override val queueName: String = "$SERVICES_PREFIX${identity.toBase58String()}"
override val queueName: String = "$PEERS_PREFIX${identity.toBase58String()}"
}
/** The config object is used to pass in the passwords for the certificate KeyStore and TrustStore */
@ -106,11 +101,12 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
}
}
fun getArtemisPeerAddress(nodeInfo: NodeInfo): ArtemisPeerAddress {
return if (nodeInfo.advertisedServices.any { it.info.type == ServiceType.networkMap }) {
NetworkMapAddress(nodeInfo.addresses.first())
// Used for bridges creation.
fun getArtemisPeerAddress(party: Party, address: NetworkHostAndPort, netMapName: CordaX500Name? = null): ArtemisPeerAddress {
return if (party.name == netMapName) {
NetworkMapAddress(address)
} else {
NodeAddress.asPeer(nodeInfo.legalIdentity.owningKey, nodeInfo.addresses.first())
NodeAddress.asSingleNode(party.owningKey, address) // It also takes care of services nodes treated as peer nodes
}
}
}

View File

@ -11,7 +11,7 @@ import org.bouncycastle.asn1.x500.X500Name
sealed class ConnectionDirection {
data class Inbound(val acceptorFactoryClassName: String) : ConnectionDirection()
data class Outbound(
val expectedCommonName: CordaX500Name? = null,
val expectedCommonNames: Set<CordaX500Name> = emptySet(), // TODO SNI? Or we need a notion of node's network identity?
val connectorFactoryClassName: String = NettyConnectorFactory::class.java.name
) : ConnectionDirection()
}
@ -67,7 +67,7 @@ class ArtemisTcpTransport {
TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME to CIPHER_SUITES.joinToString(","),
TransportConstants.ENABLED_PROTOCOLS_PROP_NAME to "TLSv1.2",
TransportConstants.NEED_CLIENT_AUTH_PROP_NAME to true,
VERIFY_PEER_LEGAL_NAME to (direction as? ConnectionDirection.Outbound)?.expectedCommonName
VERIFY_PEER_LEGAL_NAME to (direction as? ConnectionDirection.Outbound)?.expectedCommonNames
)
options.putAll(tlsOptions)
}

View File

@ -14,6 +14,7 @@ import net.corda.testing.BOB
import net.corda.core.utilities.unwrap
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
import net.corda.nodeapi.User
import net.corda.testing.chooseIdentity
import net.corda.testing.driver.driver
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
@ -30,7 +31,7 @@ class CordappScanningDriverTest {
val initiatedFlowClass = alice.rpcClientToNode()
.start(user.username, user.password)
.proxy
.startFlow(::ReceiveFlow, bob.nodeInfo.legalIdentity)
.startFlow(::ReceiveFlow, bob.nodeInfo.chooseIdentity())
.returnValue
assertThat(initiatedFlowClass.getOrThrow()).isEqualTo(SendSubClassFlow::class.java.name)
}

View File

@ -15,6 +15,7 @@ import net.corda.finance.flows.CashPaymentFlow
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
import net.corda.node.services.transactions.SimpleNotaryService
import net.corda.nodeapi.User
import net.corda.testing.chooseIdentity
import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver
import net.corda.testing.performance.div
@ -116,7 +117,7 @@ class NodePerformanceTests {
doneFutures.transpose().get()
println("STARTING PAYMENT")
startPublishingFixedRateInjector(metricRegistry, 8, 5.minutes, 100L / TimeUnit.SECONDS) {
connection.proxy.startFlow(::CashPaymentFlow, 1.DOLLARS, a.nodeInfo.legalIdentity).returnValue.get()
connection.proxy.startFlow(::CashPaymentFlow, 1.DOLLARS, a.nodeInfo.chooseIdentity()).returnValue.get()
}
}

View File

@ -32,7 +32,7 @@ class AdvertisedServiceTests {
fun `service is accessible through getAnyServiceOfType`() {
driver(startNodesInProcess = true) {
val bankA = startNode(rpcUsers = listOf(User(user, pass, setOf(startFlowPermission<ServiceTypeCheckingFlow>())))).get()
startNode(advertisedServices = setOf(ServiceInfo(serviceType, serviceName))).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)

View File

@ -23,6 +23,7 @@ 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.testing.chooseIdentity
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
@ -53,11 +54,12 @@ class BFTNotaryServiceTests {
replicaIds.map { mockNet.baseDirectory(mockNet.nextNodeId + it) },
serviceType.id,
clusterName)
val bftNotaryService = ServiceInfo(serviceType, clusterName)
val bftNotaryService = ServiceInfo(serviceType)
val notaryClusterAddresses = replicaIds.map { NetworkHostAndPort("localhost", 11000 + it * 10) }
replicaIds.forEach { replicaId ->
mockNet.createNode(
node.network.myAddress,
legalName = clusterName.copy(organisation = clusterName.organisation + replicaId),
advertisedServices = bftNotaryService,
configOverrides = {
whenever(it.bftSMaRt).thenReturn(BFTSMaRtConfiguration(replicaId, false, exposeRaces))
@ -73,7 +75,7 @@ class BFTNotaryServiceTests {
val notary = bftNotaryCluster(minClusterSize(1), true) // This true adds a sleep to expose the race.
val f = node.run {
val trivialTx = signInitialTransaction(notary) {
addOutputState(DummyContract.SingleOwnerState(owner = info.legalIdentity), DUMMY_PROGRAM_ID)
addOutputState(DummyContract.SingleOwnerState(owner = info.chooseIdentity()), DUMMY_PROGRAM_ID)
}
// Create a new consensus while the redundant replica is sleeping:
services.startFlow(NotaryFlow.Client(trivialTx)).resultFuture
@ -97,7 +99,7 @@ class BFTNotaryServiceTests {
val notary = bftNotaryCluster(clusterSize)
node.run {
val issueTx = signInitialTransaction(notary) {
addOutputState(DummyContract.SingleOwnerState(owner = info.legalIdentity), DUMMY_PROGRAM_ID)
addOutputState(DummyContract.SingleOwnerState(owner = (info.chooseIdentity())), DUMMY_PROGRAM_ID)
}
database.transaction {
services.recordTransactions(issueTx)
@ -132,7 +134,7 @@ class BFTNotaryServiceTests {
assertEquals(StateRef(issueTx.id, 0), stateRef)
assertEquals(spendTxs[successfulIndex].id, consumingTx.id)
assertEquals(0, consumingTx.inputIndex)
assertEquals(info.legalIdentity, consumingTx.requestingParty)
assertEquals(info.chooseIdentity(), consumingTx.requestingParty)
}
}
}
@ -145,7 +147,7 @@ private fun StartedNode<*>.signInitialTransaction(
): SignedTransaction {
return services.signInitialTransaction(
TransactionBuilder(notary).apply {
addCommand(dummyCommand(services.legalIdentityKey))
addCommand(dummyCommand(services.myInfo.chooseIdentity().owningKey))
block()
})
}

View File

@ -2,11 +2,11 @@ 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
import net.corda.core.messaging.startFlow
import net.corda.core.node.NodeInfo
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow
import net.corda.finance.POUNDS
@ -29,7 +29,7 @@ class DistributedServiceTests : DriverBasedTest() {
lateinit var notaries: List<NodeHandle.OutOfProcess>
lateinit var aliceProxy: CordaRPCOps
lateinit var raftNotaryIdentity: Party
lateinit var notaryStateMachines: Observable<Pair<NodeInfo, StateMachineUpdate>>
lateinit var notaryStateMachines: Observable<Pair<Party, StateMachineUpdate>>
override fun setup() = driver {
// Start Alice and 3 notaries in a RAFT cluster
@ -51,8 +51,13 @@ 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)
assertEquals(notaries.size, notaries.map { it.nodeInfo.legalIdentity }.toSet().size)
// Check that each notary has different identity as a node.
assertEquals(notaries.size, notariesIdentities.size - notaries[0].nodeInfo.advertisedServices.size)
// Connect to Alice and the notaries
fun connectRpc(node: NodeHandle): CordaRPCOps {
@ -62,7 +67,7 @@ class DistributedServiceTests : DriverBasedTest() {
aliceProxy = connectRpc(alice)
val rpcClientsToNotaries = notaries.map(::connectRpc)
notaryStateMachines = Observable.from(rpcClientsToNotaries.map { proxy ->
proxy.stateMachinesFeed().updates.map { Pair(proxy.nodeIdentity(), it) }
proxy.stateMachinesFeed().updates.map { Pair(proxy.nodeInfo().chooseIdentity(), it) }
}).flatMap { it.onErrorResumeNext(Observable.empty()) }.bufferUntilSubscribed()
runTest()
@ -82,10 +87,10 @@ class DistributedServiceTests : DriverBasedTest() {
// The state machines added in the notaries should map one-to-one to notarisation requests
val notarisationsPerNotary = HashMap<Party, Int>()
notaryStateMachines.expectEvents(isStrict = false) {
replicate<Pair<NodeInfo, StateMachineUpdate>>(50) {
replicate<Pair<Party, StateMachineUpdate>>(50) {
expect(match = { it.second is StateMachineUpdate.Added }) { (notary, update) ->
update as StateMachineUpdate.Added
notarisationsPerNotary.compute(notary.legalIdentity) { _, number -> number?.plus(1) ?: 1 }
notarisationsPerNotary.compute(notary) { _, number -> number?.plus(1) ?: 1 }
}
}
}
@ -120,10 +125,10 @@ class DistributedServiceTests : DriverBasedTest() {
val notarisationsPerNotary = HashMap<Party, Int>()
notaryStateMachines.expectEvents(isStrict = false) {
replicate<Pair<NodeInfo, StateMachineUpdate>>(30) {
replicate<Pair<Party, StateMachineUpdate>>(30) {
expect(match = { it.second is StateMachineUpdate.Added }) { (notary, update) ->
update as StateMachineUpdate.Added
notarisationsPerNotary.compute(notary.legalIdentity) { _, number -> number?.plus(1) ?: 1 }
notarisationsPerNotary.compute(notary) { _, number -> number?.plus(1) ?: 1 }
}
}
}
@ -137,6 +142,6 @@ class DistributedServiceTests : DriverBasedTest() {
}
private fun paySelf(amount: Amount<Currency>) {
aliceProxy.startFlow(::CashPaymentFlow, amount, alice.nodeInfo.legalIdentity).returnValue.getOrThrow()
aliceProxy.startFlow(::CashPaymentFlow, amount, alice.nodeInfo.chooseIdentity()).returnValue.getOrThrow()
}
}

View File

@ -16,7 +16,9 @@ import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
import net.corda.testing.chooseIdentity
import net.corda.testing.node.NodeBasedTest
import org.junit.Ignore
import org.junit.Test
import java.util.*
import kotlin.test.assertEquals
@ -25,6 +27,7 @@ import kotlin.test.assertFailsWith
class RaftNotaryServiceTests : NodeBasedTest() {
private val notaryName = CordaX500Name(organisation = "RAFT Notary Service", locality = "London", country = "GB")
@Ignore
@Test
fun `detect double spend`() {
val (bankA) = listOf(
@ -38,16 +41,16 @@ class RaftNotaryServiceTests : NodeBasedTest() {
val firstTxBuilder = TransactionBuilder(notaryParty)
.addInputState(inputState)
.addCommand(dummyCommand(bankA.services.legalIdentityKey))
.addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey))
val firstSpendTx = bankA.services.signInitialTransaction(firstTxBuilder)
val firstSpend = bankA.services.startFlow(NotaryFlow.Client(firstSpendTx))
firstSpend.resultFuture.getOrThrow()
val secondSpendBuilder = TransactionBuilder(notaryParty).withItems(inputState).run {
val dummyState = DummyContract.SingleOwnerState(0, bankA.info.legalIdentity)
val dummyState = DummyContract.SingleOwnerState(0, bankA.info.chooseIdentity())
addOutputState(dummyState, DUMMY_PROGRAM_ID)
addCommand(dummyCommand(bankA.services.legalIdentityKey))
addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey))
this
}
val secondSpendTx = bankA.services.signInitialTransaction(secondSpendBuilder)
@ -60,7 +63,7 @@ class RaftNotaryServiceTests : NodeBasedTest() {
private fun issueState(node: StartedNode<*>, notary: Party): StateAndRef<*> {
return node.database.transaction {
val builder = DummyContract.generateInitial(Random().nextInt(), notary, node.info.legalIdentity.ref(0))
val builder = DummyContract.generateInitial(Random().nextInt(), notary, node.info.chooseIdentity().ref(0))
val stx = node.services.signInitialTransaction(builder)
node.services.recordTransactions(stx)
StateAndRef(builder.outputStates().first(), StateRef(stx.id, 0))

View File

@ -9,6 +9,7 @@ import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.unwrap
import net.corda.testing.ALICE
import net.corda.testing.BOB
import net.corda.testing.chooseIdentity
import net.corda.testing.node.NodeBasedTest
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
@ -21,7 +22,7 @@ class FlowVersioningTest : NodeBasedTest() {
startNode(BOB.name, platformVersion = 3)).transpose().getOrThrow()
bob.internals.installCoreFlow(PretendInitiatingCoreFlow::class, ::PretendInitiatedCoreFlow)
val (alicePlatformVersionAccordingToBob, bobPlatformVersionAccordingToAlice) = alice.services.startFlow(
PretendInitiatingCoreFlow(bob.info.legalIdentity)).resultFuture.getOrThrow()
PretendInitiatingCoreFlow(bob.info.chooseIdentity())).resultFuture.getOrThrow()
assertThat(alicePlatformVersionAccordingToBob).isEqualTo(2)
assertThat(bobPlatformVersionAccordingToAlice).isEqualTo(3)
}

View File

@ -11,6 +11,7 @@ import net.corda.testing.BOB
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.aliceBobAndNotary
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyState
import net.corda.testing.driver.driver
import net.corda.testing.dummyCommand
@ -28,14 +29,14 @@ class LargeTransactionsTest {
override fun call() {
val tx = TransactionBuilder(notary = DUMMY_NOTARY)
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
.addCommand(dummyCommand(serviceHub.legalIdentityKey))
.addCommand(dummyCommand(serviceHub.myInfo.chooseIdentity().owningKey))
.addAttachment(hash1)
.addAttachment(hash2)
.addAttachment(hash3)
.addAttachment(hash4)
val stx = serviceHub.signInitialTransaction(tx, serviceHub.legalIdentityKey)
val stx = serviceHub.signInitialTransaction(tx, serviceHub.myInfo.chooseIdentity().owningKey)
// Send to the other side and wait for it to trigger resolution from us.
val bob = serviceHub.networkMapCache.getNodeByLegalName(BOB.name)!!.legalIdentity
val bob = serviceHub.identityService.partyFromX500Name(BOB.name)!!
subFlow(SendTransactionFlow(bob, stx))
receive<Unit>(bob)
}

View File

@ -25,6 +25,7 @@ import net.corda.nodeapi.ArtemisMessagingComponent.Companion.PEERS_PREFIX
import net.corda.nodeapi.RPCApi
import net.corda.nodeapi.User
import net.corda.nodeapi.config.SSLConfiguration
import net.corda.testing.chooseIdentity
import net.corda.testing.configureTestSSL
import net.corda.testing.messaging.SimpleMQClient
import net.corda.testing.node.NodeBasedTest
@ -86,7 +87,7 @@ abstract class MQSecurityTest : NodeBasedTest() {
@Test
fun `create queue for peer which has not been communicated with`() {
val bob = startNode(BOB.name).getOrThrow()
assertAllQueueCreationAttacksFail("$PEERS_PREFIX${bob.info.legalIdentity.owningKey.toBase58String()}")
assertAllQueueCreationAttacksFail("$PEERS_PREFIX${bob.info.chooseIdentity().owningKey.toBase58String()}")
}
@Test
@ -219,7 +220,7 @@ abstract class MQSecurityTest : NodeBasedTest() {
private fun startBobAndCommunicateWithAlice(): Party {
val bob = startNode(BOB.name).getOrThrow()
bob.internals.registerInitiatedFlow(ReceiveFlow::class.java)
val bobParty = bob.info.legalIdentity
val bobParty = bob.info.chooseIdentity()
// Perform a protocol exchange to force the peer queue to be created
alice.services.startFlow(SendFlow(bobParty, 0)).resultFuture.getOrThrow()
return bobParty

View File

@ -22,6 +22,7 @@ import net.corda.node.utilities.ServiceIdentityGenerator
import net.corda.testing.*
import net.corda.testing.node.NodeBasedTest
import org.assertj.core.api.Assertions.assertThat
import org.junit.Ignore
import org.junit.Test
import java.util.*
import java.util.concurrent.CountDownLatch
@ -68,25 +69,25 @@ class P2PMessagingTest : NodeBasedTest() {
RaftValidatingNotaryService.type.id,
DISTRIBUTED_SERVICE_NAME)
val distributedService = ServiceInfo(RaftValidatingNotaryService.type, DISTRIBUTED_SERVICE_NAME)
val notaryClusterAddress = freeLocalHostAndPort()
startNetworkMapNode(
DUMMY_MAP.name,
advertisedServices = setOf(distributedService),
advertisedServices = setOf(ServiceInfo(RaftValidatingNotaryService.type, DUMMY_MAP.name.copy(commonName = "DistributedService"))),
configOverrides = mapOf("notaryNodeAddress" to notaryClusterAddress.toString()))
val (serviceNode2, alice) = listOf(
startNode(
SERVICE_2_NAME,
advertisedServices = setOf(distributedService),
advertisedServices = setOf(ServiceInfo(RaftValidatingNotaryService.type, SERVICE_2_NAME.copy(commonName = "DistributedService"))),
configOverrides = mapOf(
"notaryNodeAddress" to freeLocalHostAndPort().toString(),
"notaryClusterAddresses" to listOf(notaryClusterAddress.toString()))),
startNode(ALICE.name)
).transpose().getOrThrow()
assertAllNodesAreUsed(listOf(networkMapNode, serviceNode2), DISTRIBUTED_SERVICE_NAME, alice)
assertAllNodesAreUsed(listOf(networkMapNode, serviceNode2), SERVICE_2_NAME.copy(commonName = "DistributedService"), alice)
}
@Ignore
@Test
fun `communicating with a distributed service which we're part of`() {
val distributedService = startNotaryCluster(DISTRIBUTED_SERVICE_NAME, 2).getOrThrow()
@ -182,7 +183,7 @@ class P2PMessagingTest : NodeBasedTest() {
)
distributedServiceNodes.forEach {
val nodeName = it.info.legalIdentity.name
val nodeName = it.info.chooseIdentity().name
it.network.addMessageHandler(dummyTopic) { netMessage, _ ->
crashingNodes.requestsReceived.incrementAndGet()
crashingNodes.firstRequestReceived.countDown()

View File

@ -5,7 +5,6 @@ import net.corda.core.concurrent.CordaFuture
import net.corda.core.crypto.random63BitValue
import net.corda.core.identity.CordaX500Name
import net.corda.core.node.NodeInfo
import net.corda.core.utilities.NonEmptySet
import net.corda.core.internal.cert
import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.seconds
@ -44,7 +43,7 @@ class P2PSecurityTest : NodeBasedTest() {
@Test
fun `register with the network map service using a legal name different from the TLS CN`() {
startSimpleNode(DUMMY_BANK_A.name, DUMMY_CA.certificate.cert).use {
startSimpleNode(DUMMY_BANK_A.name, DEV_TRUST_ROOT.cert).use {
// Register with the network map using a different legal name
val response = it.registerWithNetworkMap(DUMMY_BANK_B.name)
// We don't expect a response because the network map's host verification will prevent a connection back
@ -60,7 +59,7 @@ class P2PSecurityTest : NodeBasedTest() {
val config = testNodeConfiguration(
baseDirectory = baseDirectory(legalName),
myLegalName = legalName).also {
whenever(it.networkMapService).thenReturn(NetworkMapInfo(networkMapNode.internals.configuration.p2pAddress, networkMapNode.info.legalIdentity.name))
whenever(it.networkMapService).thenReturn(NetworkMapInfo(networkMapNode.internals.configuration.p2pAddress, networkMapNode.info.chooseIdentity().name))
}
config.configureWithDevSSLCertificate() // This creates the node's TLS cert with the CN as the legal name
return SimpleNode(config, trustRoot = trustRoot).apply { start() }
@ -68,7 +67,7 @@ class P2PSecurityTest : NodeBasedTest() {
private fun SimpleNode.registerWithNetworkMap(registrationName: CordaX500Name): CordaFuture<NetworkMapService.RegistrationResponse> {
val legalIdentity = getTestPartyAndCertificate(registrationName, identity.public)
val nodeInfo = NodeInfo(listOf(MOCK_HOST_AND_PORT), legalIdentity, NonEmptySet.of(legalIdentity), 1, serial = 1)
val nodeInfo = NodeInfo(listOf(MOCK_HOST_AND_PORT), listOf(legalIdentity), 1, serial = 1)
val registration = NodeRegistration(nodeInfo, System.currentTimeMillis(), AddOrRemove.ADD, Instant.MAX)
val request = RegistrationRequest(registration.toWire(keyService, identity.public), network.myAddress)
return network.sendRequest<NetworkMapService.RegistrationResponse>(NetworkMapService.REGISTER_TOPIC, request, networkMapNode.network.myAddress)

View File

@ -22,6 +22,7 @@ import net.corda.node.services.FlowPermissions
import net.corda.node.services.transactions.SimpleNotaryService
import net.corda.nodeapi.User
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.driver.driver
import org.junit.Test
import java.lang.management.ManagementFactory
@ -40,7 +41,7 @@ class NodeStatePersistenceTests {
startNode(providedName = DUMMY_NOTARY.name, advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type))).getOrThrow()
var nodeHandle = startNode(rpcUsers = listOf(user)).getOrThrow()
val nodeName = nodeHandle.nodeInfo.legalIdentity.name
val nodeName = nodeHandle.nodeInfo.chooseIdentity().name
nodeHandle.rpcClientToNode().start(user.username, user.password).use {
it.proxy.startFlow(::SendMessageFlow, message).returnValue.getOrThrow()
}
@ -139,7 +140,7 @@ class SendMessageFlow(private val message: Message) : FlowLogic<SignedTransactio
progressTracker.currentStep = GENERATING_TRANSACTION
val messageState = MessageState(message = message, by = serviceHub.myInfo.legalIdentity)
val messageState = MessageState(message = message, by = serviceHub.myInfo.chooseIdentity())
val txCommand = Command(MessageContract.Commands.Send(), messageState.participants.map { it.owningKey })
val txBuilder = TransactionBuilder(notary).withItems(StateAndContract(messageState, MESSAGE_CONTRACT_PROGRAM_ID), txCommand)

View File

@ -133,6 +133,7 @@ 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 info: NodeInfo
protected lateinit var checkpointStorage: CheckpointStorage
protected lateinit var smm: StateMachineManager
@ -380,7 +381,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
_services = ServiceHubInternalImpl()
attachments = NodeAttachmentService(services.monitoringService.metrics)
cordappProvider = CordappProvider(attachments, makeCordappLoader())
val legalIdentity = obtainIdentity()
legalIdentity = obtainIdentity()
network = makeMessagingService(legalIdentity)
info = makeInfo(legalIdentity)
@ -410,9 +411,10 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
private fun makeInfo(legalIdentity: PartyAndCertificate): NodeInfo {
val advertisedServiceEntries = makeServiceEntries()
val allIdentities = advertisedServiceEntries.map { it.identity }.toSet() // TODO Add node's legalIdentity (after services removal).
val allIdentitiesList = mutableListOf(legalIdentity)
allIdentitiesList.addAll(advertisedServiceEntries.map { it.identity }) // TODO Will we keep service identities here, for example notaries?
val addresses = myAddresses() // TODO There is no support for multiple IP addresses yet.
return NodeInfo(addresses, legalIdentity, allIdentities, platformVersion, advertisedServiceEntries, platformClock.instant().toEpochMilli())
return NodeInfo(addresses, allIdentitiesList, platformVersion, advertisedServiceEntries, platformClock.instant().toEpochMilli())
}
/**
@ -520,7 +522,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
"Initial network map address must indicate a node that provides a network map service"
}
val address: SingleMessageRecipient = networkMapAddress ?:
network.getAddressOfParty(PartyInfo.Node(info)) as SingleMessageRecipient
network.getAddressOfParty(PartyInfo.SingleNode(services.myInfo.legalIdentitiesAndCerts.first().party, info.addresses)) as SingleMessageRecipient
// Register for updates, even if we're the one running the network map.
return sendNetworkMapRegistration(address).flatMap { (error) ->
check(error == null) { "Unable to register with the network map service: $error" }
@ -534,7 +536,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
val instant = platformClock.instant()
val expires = instant + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
val reg = NodeRegistration(info, info.serial, ADD, expires)
val request = RegistrationRequest(reg.toWire(services.keyManagementService, info.legalIdentityAndCert.owningKey), network.myAddress)
val request = RegistrationRequest(reg.toWire(services.keyManagementService, info.legalIdentitiesAndCerts.first().owningKey), network.myAddress)
return network.sendRequest(NetworkMapService.REGISTER_TOPIC, request, networkMapAddress)
}
@ -577,12 +579,14 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
val caCertificates: Array<X509Certificate> = listOf(legalIdentity.certificate, clientCa?.certificate?.cert)
.filterNotNull()
.toTypedArray()
val service = PersistentIdentityService(setOf(info.legalIdentityAndCert), trustRoot = trustRoot, caCertificates = *caCertificates)
services.networkMapCache.partyNodes.forEach { service.verifyAndRegisterIdentity(it.legalIdentityAndCert) }
val service = PersistentIdentityService(info.legalIdentitiesAndCerts.toSet(), trustRoot = trustRoot, caCertificates = *caCertificates)
services.networkMapCache.partyNodes.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) {
service.verifyAndRegisterIdentity(mapChange.node.legalIdentityAndCert)
mapChange.node.legalIdentitiesAndCerts.forEach {
service.verifyAndRegisterIdentity(it)
}
}
}
return service
@ -712,7 +716,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
makeIdentityService(
trustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA),
caKeyStore.certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA),
info.legalIdentityAndCert)
legalIdentity)
}
override val attachments: AttachmentStorage get() = this@AbstractNode.attachments
override val networkService: MessagingService get() = network
@ -726,8 +730,9 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
return cordappServices.getInstance(type) ?: throw IllegalArgumentException("Corda service ${type.name} does not exist")
}
override fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator): FlowStateMachineImpl<T> {
return serverThread.fetchFrom { smm.add(logic, flowInitiator) }
override fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate?): FlowStateMachineImpl<T> {
check(me == null || me in myInfo.legalIdentitiesAndCerts) { "Attempt to start a flow with legal identity not belonging to this node." }
return serverThread.fetchFrom { smm.add(logic, flowInitiator, me) }
}
override fun getFlowFactory(initiatingFlowClass: Class<out FlowLogic<*>>): InitiatedFlowFactory<*>? {

View File

@ -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
@ -110,7 +111,7 @@ class CordaRPCOpsImpl(
}
}
override fun nodeIdentity(): NodeInfo {
override fun nodeInfo(): NodeInfo {
return services.myInfo
}
@ -142,10 +143,11 @@ class CordaRPCOpsImpl(
private fun <T> startFlow(logicType: Class<out FlowLogic<T>>, args: Array<out Any?>): FlowStateMachineImpl<T> {
require(logicType.isAnnotationPresent(StartableByRPC::class.java)) { "${logicType.name} was not designed for RPC" }
val me = services.myInfo.legalIdentitiesAndCerts.first() // TODO RPC flows should have mapping user -> identity that should be resolved automatically on starting flow.
val rpcContext = getRpcContext()
rpcContext.requirePermission(startFlowPermission(logicType))
val currentUser = FlowInitiator.RPC(rpcContext.currentUser.username)
return services.invokeFlowAsync(logicType, currentUser, *args)
return services.invokeFlowAsync(logicType, currentUser, me, *args)
}
override fun attachmentExists(id: SecureHash): Boolean {

View File

@ -96,7 +96,7 @@ open class NodeStartup(val args: Array<String>) {
printPluginsAndServices(node.internals)
node.internals.nodeReadyFuture.thenMatch({
val elapsed = (System.currentTimeMillis() - startTime) / 10 / 100.0
val name = node.info.legalIdentity.name.organisation
val name = node.info.legalIdentitiesAndCerts.first().name.organisation
Node.printBasicNodeInfo("Node for \"$name\" started up and registered in $elapsed sec")
// Don't start the shell if there's no console attached.

View File

@ -57,7 +57,7 @@ class SwapIdentitiesHandler(val otherSide: Party, val revocationEnabled: Boolean
override fun call(): Unit {
val revocationEnabled = false
progressTracker.currentStep = SENDING_KEY
val legalIdentityAnonymous = serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.legalIdentityAndCert, revocationEnabled)
val legalIdentityAnonymous = serviceHub.keyManagementService.freshKeyAndCert(ourIdentity, revocationEnabled)
sendAndReceive<PartyAndCertificate>(otherSide, legalIdentityAnonymous).unwrap { confidentialIdentity ->
SwapIdentitiesFlow.validateAndRegisterIdentity(serviceHub.identityService, otherSide, confidentialIdentity)
}

View File

@ -5,6 +5,8 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FlowInitiator
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StateMachineRunId
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.VisibleForTesting
import net.corda.core.messaging.DataFeed
@ -29,9 +31,9 @@ interface NetworkMapCacheInternal : NetworkMapCache {
/**
* Deregister from updates from the given map service.
* @param network the network messaging service.
* @param service the network map service to fetch current state from.
* @param mapParty the network map service party to fetch current state from.
*/
fun deregisterForUpdates(network: MessagingService, service: NodeInfo): CordaFuture<Unit>
fun deregisterForUpdates(network: MessagingService, mapParty: Party): CordaFuture<Unit>
/**
* Add a network map service; fetches a copy of the latest map from the service and subscribes to any further
@ -116,7 +118,7 @@ interface ServiceHubInternal : ServiceHub {
* Starts an already constructed flow. Note that you must be on the server thread to call this method.
* @param flowInitiator indicates who started the flow, see: [FlowInitiator].
*/
fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator): FlowStateMachineImpl<T>
fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate? = null): FlowStateMachineImpl<T>
/**
* Will check [logicType] and [args] against a whitelist and if acceptable then construct and initiate the flow.
@ -129,11 +131,12 @@ interface ServiceHubInternal : ServiceHub {
fun <T> invokeFlowAsync(
logicType: Class<out FlowLogic<T>>,
flowInitiator: FlowInitiator,
me: PartyAndCertificate? = null,
vararg args: Any?): FlowStateMachineImpl<T> {
val logicRef = FlowLogicRefFactoryImpl.createForRPC(logicType, *args)
@Suppress("UNCHECKED_CAST")
val logic = FlowLogicRefFactoryImpl.toFlowLogic(logicRef) as FlowLogic<T>
return startFlow(logic, flowInitiator)
return startFlow(logic, flowInitiator, me)
}
fun getFlowFactory(initiatingFlowClass: Class<out FlowLogic<*>>): InitiatedFlowFactory<*>?

View File

@ -5,6 +5,7 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.toStringShort
import net.corda.core.identity.*
import net.corda.core.internal.cert
import net.corda.core.internal.toX509CertHolder
import net.corda.core.node.services.IdentityService
import net.corda.core.node.services.UnknownAnonymousPartyException
import net.corda.core.serialization.SingletonSerializeAsToken
@ -112,7 +113,16 @@ class PersistentIdentityService(identities: Iterable<PartyAndCertificate> = empt
@Throws(CertificateExpiredException::class, CertificateNotYetValidException::class, InvalidAlgorithmParameterException::class)
override fun verifyAndRegisterIdentity(identity: PartyAndCertificate): PartyAndCertificate? {
// Validate the chain first, before we do anything clever with it
identity.verify(trustAnchor)
try {
identity.verify(trustAnchor)
} catch (e: CertPathValidatorException) {
log.error(e.localizedMessage)
log.error("Path = ")
identity.certPath.certificates.reversed().forEach {
log.error(it.toX509CertHolder().subject.toString())
}
throw e
}
log.info("Registering identity $identity")
val key = mapToKey(identity)

View File

@ -131,7 +131,7 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
if (!running) {
configureAndStartServer()
// Deploy bridge to the network map service
config.networkMapService?.let { deployBridge(NetworkMapAddress(it.address), it.legalName) }
config.networkMapService?.let { deployBridge(NetworkMapAddress(it.address), setOf(it.legalName)) }
networkChangeHandle = networkMapCache.changed.subscribe { updateBridgesOnNetworkChange(it) }
running = true
}
@ -295,36 +295,24 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
private fun deployBridgesFromNewQueue(queueName: String) {
log.debug { "Queue created: $queueName, deploying bridge(s)" }
fun deployBridgeToPeer(nodeInfo: NodeInfo) {
log.debug("Deploying bridge for $queueName to $nodeInfo")
val address = nodeInfo.addresses.first() // TODO Load balancing.
deployBridge(queueName, address, nodeInfo.legalIdentity.name)
val address = nodeInfo.addresses.first()
deployBridge(queueName, address, nodeInfo.legalIdentitiesAndCerts.map { it.name }.toSet())
}
when {
queueName.startsWith(PEERS_PREFIX) -> try {
if (queueName.startsWith(PEERS_PREFIX)) {
try {
val identity = parsePublicKeyBase58(queueName.substring(PEERS_PREFIX.length))
val nodeInfo = networkMapCache.getNodeByLegalIdentityKey(identity)
if (nodeInfo != null) {
deployBridgeToPeer(nodeInfo)
val nodeInfos = networkMapCache.getNodesByLegalIdentityKey(identity)
if (nodeInfos.isNotEmpty()) {
nodeInfos.forEach { deployBridgeToPeer(it) }
} else {
log.error("Queue created for a peer that we don't know from the network map: $queueName")
}
} catch (e: AddressFormatException) {
log.error("Flow violation: Could not parse peer queue name as Base 58: $queueName")
}
queueName.startsWith(SERVICES_PREFIX) -> try {
val identity = parsePublicKeyBase58(queueName.substring(SERVICES_PREFIX.length))
val nodeInfos = networkMapCache.getNodesByAdvertisedServiceIdentityKey(identity)
// Create a bridge for each node advertising the service.
for (nodeInfo in nodeInfos) {
deployBridgeToPeer(nodeInfo)
}
} catch (e: AddressFormatException) {
log.error("Flow violation: Could not parse service queue name as Base 58: $queueName")
}
}
}
@ -339,16 +327,14 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
private fun updateBridgesOnNetworkChange(change: MapChange) {
log.debug { "Updating bridges on network map change: ${change.node}" }
fun gatherAddresses(node: NodeInfo): Sequence<ArtemisPeerAddress> {
val peerAddress = getArtemisPeerAddress(node)
val addresses = mutableListOf(peerAddress)
node.advertisedServices.mapTo(addresses) { NodeAddress.asService(it.identity.owningKey, peerAddress.hostAndPort) }
return addresses.asSequence()
val address = node.addresses.first()
return node.legalIdentitiesAndCerts.map { getArtemisPeerAddress(it.party, address, config.networkMapService?.legalName) }.asSequence()
}
fun deployBridges(node: NodeInfo) {
gatherAddresses(node)
.filter { queueExists(it.queueName) && !bridgeExists(it.bridgeName) }
.forEach { deployBridge(it, node.legalIdentity.name) }
.forEach { deployBridge(it, node.legalIdentitiesAndCerts.map { it.name }.toSet()) }
}
fun destroyBridges(node: NodeInfo) {
@ -372,8 +358,8 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
}
}
private fun deployBridge(address: ArtemisPeerAddress, legalName: CordaX500Name) {
deployBridge(address.queueName, address.hostAndPort, legalName)
private fun deployBridge(address: ArtemisPeerAddress, legalNames: Set<CordaX500Name>) {
deployBridge(address.queueName, address.hostAndPort, legalNames)
}
private fun createTcpTransport(connectionDirection: ConnectionDirection, host: String, port: Int, enableSSL: Boolean = true) =
@ -385,10 +371,10 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
* as defined by ArtemisAddress.queueName. A bridge is then created to forward messages from this queue to the node's
* P2P address.
*/
private fun deployBridge(queueName: String, target: NetworkHostAndPort, legalName: CordaX500Name) {
private fun deployBridge(queueName: String, target: NetworkHostAndPort, legalNames: Set<CordaX500Name>) {
val connectionDirection = ConnectionDirection.Outbound(
connectorFactoryClassName = VerifyingNettyConnectorFactory::class.java.name,
expectedCommonName = legalName
expectedCommonNames = legalNames
)
val tcpTransport = createTcpTransport(connectionDirection, target.host, target.port)
tcpTransport.params[ArtemisMessagingServer::class.java.name] = this
@ -424,9 +410,9 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
private fun getBridgeName(queueName: String, hostAndPort: NetworkHostAndPort): String = "$queueName -> $hostAndPort"
// This is called on one of Artemis' background threads
internal fun hostVerificationFail(expectedLegalName: CordaX500Name, errorMsg: String?) {
internal fun hostVerificationFail(expectedLegalNames: Set<CordaX500Name>, errorMsg: String?) {
log.error(errorMsg)
if (expectedLegalName == config.networkMapService?.legalName) {
if (config.networkMapService?.legalName in expectedLegalNames) {
// If the peer that failed host verification was the network map node then we're in big trouble and need to bail!
_networkMapConnectionFuture!!.setException(IOException("${config.networkMapService} failed host verification check"))
}
@ -492,7 +478,8 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>,
override fun createConnection(): Connection? {
val connection = super.createConnection() as? NettyConnection
if (sslEnabled && connection != null) {
val expectedLegalName = configuration[ArtemisTcpTransport.VERIFY_PEER_LEGAL_NAME] as CordaX500Name
@Suppress("UNCHECKED_CAST")
val expectedLegalNames = (configuration[ArtemisTcpTransport.VERIFY_PEER_LEGAL_NAME] ?: emptySet<CordaX500Name>()) as Set<CordaX500Name>
try {
val session = connection.channel
.pipeline()
@ -500,22 +487,27 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>,
.engine()
.session
// Checks the peer name is the one we are expecting.
// TODO Some problems here: after introduction of multiple legal identities on the node and removal of the main one,
// we run into the issue, who are we connecting to. There are some solutions to that: advertise `network identity`;
// have mapping port -> identity (but, design doc says about removing SingleMessageRecipient and having just NetworkHostAndPort,
// it was convenient to store that this way); SNI.
val peerLegalName = CordaX500Name.parse(session.peerPrincipal.name)
require(peerLegalName == expectedLegalName) {
"Peer has wrong CN - expected $expectedLegalName but got $peerLegalName. This is either a fatal " +
val expectedLegalName = expectedLegalNames.singleOrNull { it == peerLegalName }
require(expectedLegalName != null) {
"Peer has wrong CN - expected $expectedLegalNames but got $peerLegalName. This is either a fatal " +
"misconfiguration by the remote peer or an SSL man-in-the-middle attack!"
}
// Make sure certificate has the same name.
val peerCertificateName = CordaX500Name.build(X500Principal(session.peerCertificateChain[0].subjectDN.name))
require(peerCertificateName == expectedLegalName) {
"Peer has wrong subject name in the certificate - expected $expectedLegalName but got $peerCertificateName. This is either a fatal " +
"Peer has wrong subject name in the certificate - expected $expectedLegalNames but got $peerCertificateName. This is either a fatal " +
"misconfiguration by the remote peer or an SSL man-in-the-middle attack!"
}
X509Utilities.validateCertificateChain(session.localCertificates.last() as java.security.cert.X509Certificate, *session.peerCertificates)
server.onTcpConnection(peerLegalName)
} catch (e: IllegalArgumentException) {
connection.close()
server.hostVerificationFail(expectedLegalName, e.message)
server.hostVerificationFail(expectedLegalNames, e.message)
return null
}
}

View File

@ -169,7 +169,7 @@ class NodeMessagingClient(override val config: NodeConfiguration,
* Apart from the NetworkMapService this is the only other address accessible to the node outside of lookups against the NetworkMapCache.
*/
override val myAddress: SingleMessageRecipient = if (myIdentity != null) {
NodeAddress.asPeer(myIdentity, advertisedAddress)
NodeAddress.asSingleNode(myIdentity, advertisedAddress)
} else {
NetworkMapAddress(advertisedAddress)
}
@ -622,10 +622,13 @@ class NodeMessagingClient(override val config: NodeConfiguration,
}
}
// TODO Rethink PartyInfo idea and merging PeerAddress/ServiceAddress (the only difference is that Service address doesn't hold host and port)
override fun getAddressOfParty(partyInfo: PartyInfo): MessageRecipients {
return when (partyInfo) {
is PartyInfo.Node -> getArtemisPeerAddress(partyInfo.node)
is PartyInfo.Service -> ServiceAddress(partyInfo.service.identity.owningKey)
is PartyInfo.SingleNode -> {
getArtemisPeerAddress(partyInfo.party, partyInfo.addresses.first(), config.networkMapService?.legalName)
}
is PartyInfo.DistributedNode -> ServiceAddress(partyInfo.party.owningKey)
}
}
}

View File

@ -251,8 +251,10 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal,
logger.error(msg, e)
return RegistrationResponse(msg)
}
val node = change.node
// Get identity from signature on node's registration and use it as an index.
val identity = node.legalIdentitiesAndCerts.singleOrNull { request.wireReg.sig.by == it.owningKey }
identity ?: return RegistrationResponse("Key from signature on the node registration wasn't found in NodeInfo")
if (node.platformVersion < minimumPlatformVersion) {
return RegistrationResponse("Minimum platform version requirement not met: $minimumPlatformVersion")
@ -262,7 +264,7 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal,
// in on different threads, there is no risk of a race condition while checking
// sequence numbers.
val registrationInfo = try {
nodeRegistrations.compute(node.legalIdentityAndCert) { _, existing: NodeRegistrationInfo? ->
nodeRegistrations.compute(identity) { _, existing: NodeRegistrationInfo? ->
require(!((existing == null || existing.reg.type == REMOVE) && change.type == REMOVE)) {
"Attempting to de-register unknown node"
}
@ -352,7 +354,9 @@ data class NodeRegistration(val node: NodeInfo, val serial: Long, val type: AddO
class WireNodeRegistration(raw: SerializedBytes<NodeRegistration>, sig: DigitalSignature.WithKey) : SignedData<NodeRegistration>(raw, sig) {
@Throws(IllegalArgumentException::class)
override fun verifyData(data: NodeRegistration) {
require(data.node.legalIdentity.owningKey.isFulfilledBy(sig.by))
// Check that the registration is fulfilled by any of node's identities.
// TODO It may cause some problems with distributed services? We loose node's main identity. Should be all signatures instead of isFulfilledBy?
require(data.node.legalIdentitiesAndCerts.any { it.owningKey.isFulfilledBy(sig.by) })
}
}

View File

@ -57,7 +57,8 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
private var registeredForPush = false
// 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.
override val partyNodes: List<NodeInfo> get() = registeredNodes.map { it.value }
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)
private val _changed = PublishSubject.create<MapChange>()
// We use assignment here so that multiple subscribers share the same wrapped Observable.
@ -66,7 +67,6 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
private val _registrationFuture = openFuture<Void?>()
override val nodeReady: CordaFuture<Void?> get() = _registrationFuture
protected val registeredNodes: MutableMap<PublicKey, NodeInfo> = Collections.synchronizedMap(HashMap())
private var _loadDBSuccess: Boolean = false
override val loadDBSuccess get() = _loadDBSuccess
@ -76,13 +76,13 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
override fun getPartyInfo(party: Party): PartyInfo? {
val nodes = serviceHub.database.transaction { queryByIdentityKey(party.owningKey) }
if (nodes.size == 1 && nodes[0].legalIdentity == party) {
return PartyInfo.Node(nodes[0])
if (nodes.size == 1 && party in nodes[0].legalIdentities) {
return PartyInfo.SingleNode(party, nodes[0].addresses)
}
for (node in nodes) {
for (service in node.advertisedServices) {
if (service.identity.party == party) {
return PartyInfo.Service(service)
return PartyInfo.DistributedNode(party)
}
}
}
@ -90,14 +90,14 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
}
// TODO See comment to queryByLegalName why it's left like that.
override fun getNodeByLegalName(principal: CordaX500Name): NodeInfo? = partyNodes.singleOrNull { it.legalIdentity.name == principal }
override fun getNodeByLegalName(principal: CordaX500Name): NodeInfo? = partyNodes.singleOrNull { principal in it.legalIdentities.map { it.name } }
//serviceHub!!.database.transaction { queryByLegalName(principal).firstOrNull() }
override fun getNodeByLegalIdentityKey(identityKey: PublicKey): NodeInfo? =
serviceHub.database.transaction { queryByIdentityKey(identityKey).firstOrNull() }
override fun getNodesByLegalIdentityKey(identityKey: PublicKey): List<NodeInfo> =
serviceHub.database.transaction { queryByIdentityKey(identityKey) }
override fun getNodeByLegalIdentity(party: AbstractParty): NodeInfo? {
val wellKnownParty = serviceHub.identityService.partyFromAnonymous(party)
return wellKnownParty?.let {
getNodeByLegalIdentityKey(it.owningKey)
getNodesByLegalIdentityKey(it.owningKey).singleOrNull()
}
}
@ -143,7 +143,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
override fun addNode(node: NodeInfo) {
synchronized(_changed) {
val previousNode = registeredNodes.put(node.legalIdentity.owningKey, node)
val previousNode = registeredNodes.put(node.legalIdentities.first().owningKey, node) // TODO hack... we left the first one as special one
if (previousNode == null) {
serviceHub.database.transaction {
updateInfoDB(node)
@ -160,7 +160,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
override fun removeNode(node: NodeInfo) {
synchronized(_changed) {
registeredNodes.remove(node.legalIdentity.owningKey)
registeredNodes.remove(node.legalIdentities.first().owningKey)
serviceHub.database.transaction {
removeInfoDB(node)
changePublisher.onNext(MapChange.Removed(node))
@ -170,13 +170,14 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
/**
* Unsubscribes from updates from the given map service.
* @param service the network map service to listen to updates from.
* @param mapParty the network map service party to listen to updates from.
*/
override fun deregisterForUpdates(network: MessagingService, service: NodeInfo): CordaFuture<Unit> {
override fun deregisterForUpdates(network: MessagingService, mapParty: Party): CordaFuture<Unit> {
// Fetch the network map and register for updates at the same time
val req = NetworkMapService.SubscribeRequest(false, network.myAddress)
// `network.getAddressOfParty(partyInfo)` is a work-around for MockNetwork and InMemoryMessaging to get rid of SingleMessageRecipient in NodeInfo.
val address = network.getAddressOfParty(PartyInfo.Node(service))
val address = getPartyInfo(mapParty)?.let{ network.getAddressOfParty(it) } ?:
throw IllegalArgumentException("Can't deregister for updates, don't know the party: $mapParty")
val future = network.sendRequest<SubscribeResponse>(NetworkMapService.SUBSCRIPTION_TOPIC, req, address).map {
if (it.confirmed) Unit else throw NetworkCacheError.DeregistrationFailed()
}
@ -255,7 +256,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
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?
val info = findByIdentityKey(session, nodeInfo.legalIdentity.owningKey)
val info = findByIdentityKey(session, nodeInfo.legalIdentitiesAndCerts.first().owningKey)
val nodeInfoEntry = generateMappedObject(nodeInfo)
if (info.isNotEmpty()) {
nodeInfoEntry.id = info[0].id
@ -268,7 +269,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
private fun removeInfoDB(nodeInfo: NodeInfo) {
createSession {
val info = findByIdentityKey(it, nodeInfo.legalIdentity.owningKey).single()
val info = findByIdentityKey(it, nodeInfo.legalIdentitiesAndCerts.first().owningKey).single()
it.remove(info)
}
}
@ -317,9 +318,9 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
return NodeInfoSchemaV1.PersistentNodeInfo(
id = 0,
addresses = nodeInfo.addresses.map { NodeInfoSchemaV1.DBHostAndPort.fromHostAndPort(it) },
legalIdentitiesAndCerts = nodeInfo.legalIdentitiesAndCerts.map { NodeInfoSchemaV1.DBPartyAndCertificate(it) }.toSet()
// TODO It's workaround to keep the main identity, will be removed in future PR getting rid of services.
+ NodeInfoSchemaV1.DBPartyAndCertificate(nodeInfo.legalIdentityAndCert, isMain = true),
// TODO Another ugly hack with special first identity...
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

View File

@ -11,6 +11,7 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.random63BitValue
import net.corda.core.flows.*
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.*
import net.corda.core.internal.concurrent.OpenFuture
import net.corda.core.internal.concurrent.openFuture
@ -35,7 +36,8 @@ class FlowPermissionException(message: String) : FlowException(message)
class FlowStateMachineImpl<R>(override val id: StateMachineRunId,
val logic: FlowLogic<R>,
scheduler: FiberScheduler,
override val flowInitiator: FlowInitiator) : Fiber<Unit>(id.toString(), scheduler), FlowStateMachine<R> {
override val flowInitiator: FlowInitiator,
override val ourIdentity: PartyAndCertificate) : Fiber<Unit>(id.toString(), scheduler), FlowStateMachine<R> {
companion object {
// Used to work around a small limitation in Quasar.
private val QUASAR_UNBLOCKER = Fiber::class.staticField<Any>("SERIALIZER_BLOCKER").value

View File

@ -3,6 +3,7 @@ package net.corda.node.services.statemachine
import net.corda.core.flows.FlowException
import net.corda.core.flows.UnexpectedFlowEndException
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.castIfPossible
import net.corda.core.serialization.CordaSerializable
import net.corda.core.utilities.UntrustworthyData
@ -25,7 +26,9 @@ data class SessionInit(val initiatorSessionId: Long,
val initiatingFlowClass: String,
val flowVersion: Int,
val appName: String,
val firstPayload: Any?) : SessionMessage
val firstPayload: Any?,
// Left as a placeholder for support of multiple identities on a node. For now we choose the first one as a special one.
val otherIdentity: PartyAndCertificate? = null) : SessionMessage
data class SessionConfirm(override val initiatorSessionId: Long,
val initiatedSessionId: Long,

View File

@ -14,6 +14,7 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.random63BitValue
import net.corda.core.flows.*
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.ThreadBox
import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.internal.castIfPossible
@ -288,7 +289,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
private fun onSessionMessage(message: ReceivedMessage) {
val sessionMessage = message.data.deserialize<SessionMessage>()
val sender = serviceHub.networkMapCache.getNodeByLegalName(message.peer)?.legalIdentity
val sender = serviceHub.networkMapCache.getPeerByLegalName(message.peer)
if (sender != null) {
when (sessionMessage) {
is ExistingSessionMessage -> onExistingSessionMessage(sessionMessage, sender)
@ -370,7 +371,8 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
session.receivedMessages += ReceivedSessionMessage(sender, SessionData(session.ourSessionId, sessionInit.firstPayload))
}
openSessions[session.ourSessionId] = session
val fiber = createFiber(flow, FlowInitiator.Peer(sender))
val meIdentity = sessionInit.otherIdentity ?: serviceHub.myInfo.legalIdentitiesAndCerts.first()
val fiber = createFiber(flow, FlowInitiator.Peer(sender), meIdentity)
flowSession.sessionFlow = flow
flowSession.stateMachine = fiber
fiber.openSessions[Pair(flow, sender)] = session
@ -425,9 +427,9 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
}
}
private fun <T> createFiber(logic: FlowLogic<T>, flowInitiator: FlowInitiator): FlowStateMachineImpl<T> {
private fun <T> createFiber(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate): FlowStateMachineImpl<T> {
val id = StateMachineRunId.createRandom()
return FlowStateMachineImpl(id, logic, scheduler, flowInitiator).apply { initFiber(this) }
return FlowStateMachineImpl(id, logic, scheduler, flowInitiator, me).apply { initFiber(this) }
}
private fun initFiber(fiber: FlowStateMachineImpl<*>) {
@ -512,11 +514,11 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
*
* Note that you must be on the [executor] thread.
*/
fun <T> add(logic: FlowLogic<T>, flowInitiator: FlowInitiator): FlowStateMachineImpl<T> {
fun <T> add(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate?): FlowStateMachineImpl<T> {
// TODO: Check that logic has @Suspendable on its call method.
executor.checkOnThread()
val fiber = database.transaction {
val fiber = createFiber(logic, flowInitiator)
val fiber = createFiber(logic, flowInitiator, me ?: serviceHub.myInfo.legalIdentitiesAndCerts.first())
updateCheckpoint(fiber)
fiber
}

View File

@ -45,7 +45,7 @@ class CordappSmokeTest {
factory.create(aliceConfig).use { alice ->
alice.connect().use { connectionToAlice ->
val aliceIdentity = connectionToAlice.proxy.nodeIdentity().legalIdentity
val aliceIdentity = connectionToAlice.proxy.nodeInfo().legalIdentitiesAndCerts.first().party
val future = connectionToAlice.proxy.startFlow(::GatherContextsFlow, aliceIdentity).returnValue
val (sessionInitContext, sessionConfirmContext) = future.getOrThrow()
val selfCordappName = selfCordapp.fileName.toString().removeSuffix(".jar")

View File

@ -31,6 +31,7 @@ import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
import net.corda.node.services.transactions.SimpleNotaryService
import net.corda.nodeapi.PermissionException
import net.corda.nodeapi.User
import net.corda.testing.chooseIdentity
import net.corda.testing.expect
import net.corda.testing.expectEvents
import net.corda.testing.node.MockNetwork
@ -100,7 +101,7 @@ class CordaRPCOpsImplTest {
}
// Tell the monitoring service node to issue some cash
val recipient = aliceNode.info.legalIdentity
val recipient = aliceNode.info.chooseIdentity()
val result = rpc.startFlow(::CashIssueFlow, Amount(quantity, GBP), ref, notaryNode.info.notaryIdentity)
mockNet.runNetwork()
@ -119,7 +120,7 @@ class CordaRPCOpsImplTest {
val anonymisedRecipient = result.returnValue.getOrThrow().recipient!!
val expectedState = Cash.State(Amount(quantity,
Issued(aliceNode.info.legalIdentity.ref(ref), GBP)),
Issued(aliceNode.info.chooseIdentity().ref(ref), GBP)),
anonymisedRecipient)
// Query vault via RPC
@ -150,7 +151,7 @@ class CordaRPCOpsImplTest {
mockNet.runNetwork()
rpc.startFlow(::CashPaymentFlow, 100.DOLLARS, aliceNode.info.legalIdentity)
rpc.startFlow(::CashPaymentFlow, 100.DOLLARS, aliceNode.info.chooseIdentity())
mockNet.runNetwork()
@ -184,7 +185,7 @@ class CordaRPCOpsImplTest {
require(stx.tx.outputs.size == 1)
val signaturePubKeys = stx.sigs.map { it.by }.toSet()
// Only Alice signed, as issuer
val aliceKey = aliceNode.info.legalIdentity.owningKey
val aliceKey = aliceNode.info.chooseIdentity().owningKey
require(signaturePubKeys.size <= aliceKey.keys.size)
require(aliceKey.isFulfilledBy(signaturePubKeys))
},

View File

@ -7,11 +7,13 @@ import net.corda.core.contracts.Amount
import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FlowLogic
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.FlowStateMachine
import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.UntrustworthyData
import net.corda.node.services.identity.InMemoryIdentityService
import net.corda.node.shell.InteractiveShell
import net.corda.testing.DUMMY_CA
import net.corda.testing.DEV_TRUST_ROOT
import net.corda.testing.MEGA_CORP
import net.corda.testing.MEGA_CORP_IDENTITY
import org.junit.Test
@ -31,7 +33,7 @@ class InteractiveShellTest {
override fun call() = a
}
private val ids = InMemoryIdentityService(listOf(MEGA_CORP_IDENTITY), trustRoot = DUMMY_CA.certificate)
private val ids = InMemoryIdentityService(listOf(MEGA_CORP_IDENTITY), trustRoot = DEV_TRUST_ROOT)
private val om = JacksonSupport.createInMemoryMapper(ids, YAMLFactory())
private fun check(input: String, expected: String) {
@ -69,4 +71,4 @@ class InteractiveShellTest {
fun party() = check("party: \"${MEGA_CORP.name}\"", MEGA_CORP.name.toString())
class DummyFSM(val logic: FlowA) : FlowStateMachine<Any?> by mock()
}
}

View File

@ -96,8 +96,8 @@ class TwoPartyTradeFlowTests {
val aliceNode = basketOfNodes.partyNodes[0]
val bobNode = basketOfNodes.partyNodes[1]
val bankNode = basketOfNodes.partyNodes[2]
val cashIssuer = bankNode.info.legalIdentity.ref(1)
val cpIssuer = bankNode.info.legalIdentity.ref(1, 2, 3)
val cashIssuer = bankNode.info.chooseIdentity().ref(1)
val cpIssuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
aliceNode.internals.disableDBCloseOnStop()
bobNode.internals.disableDBCloseOnStop()
@ -108,8 +108,8 @@ class TwoPartyTradeFlowTests {
}
val alicesFakePaper = aliceNode.database.transaction {
fillUpForSeller(false, cpIssuer, aliceNode.info.legalIdentity,
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), null, notaryNode.info.notaryIdentity).second
fillUpForSeller(false, cpIssuer, aliceNode.info.chooseIdentity(),
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notaryNode.info.notaryIdentity).second
}
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
@ -144,7 +144,7 @@ class TwoPartyTradeFlowTests {
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
val issuer = bankNode.info.legalIdentity.ref(1)
val issuer = bankNode.info.chooseIdentity().ref(1)
aliceNode.internals.disableDBCloseOnStop()
bobNode.internals.disableDBCloseOnStop()
@ -155,8 +155,8 @@ class TwoPartyTradeFlowTests {
}
val alicesFakePaper = aliceNode.database.transaction {
fillUpForSeller(false, issuer, aliceNode.info.legalIdentity,
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), null, notaryNode.info.notaryIdentity).second
fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notaryNode.info.notaryIdentity).second
}
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
@ -197,21 +197,16 @@ class TwoPartyTradeFlowTests {
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
var bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
val issuer = bankNode.info.legalIdentity.ref(1, 2, 3)
val issuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
// Let the nodes know about each other - normally the network map would handle this
val allNodes = listOf(notaryNode, aliceNode, bobNode, bankNode)
allNodes.forEach { node ->
node.database.transaction {
allNodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity -> node.services.identityService.verifyAndRegisterIdentity(identity) }
}
}
mockNet.registerIdentities()
aliceNode.database.transaction {
aliceNode.services.identityService.verifyAndRegisterIdentity(bobNode.info.legalIdentityAndCert)
aliceNode.services.identityService.verifyAndRegisterIdentity(bobNode.info.chooseIdentityAndCert())
}
bobNode.database.transaction {
bobNode.services.identityService.verifyAndRegisterIdentity(aliceNode.info.legalIdentityAndCert)
bobNode.services.identityService.verifyAndRegisterIdentity(aliceNode.info.chooseIdentityAndCert())
}
aliceNode.internals.disableDBCloseOnStop()
bobNode.internals.disableDBCloseOnStop()
@ -226,8 +221,8 @@ class TwoPartyTradeFlowTests {
issuedBy = issuer)
}
val alicesFakePaper = aliceNode.database.transaction {
fillUpForSeller(false, issuer, aliceNode.info.legalIdentity,
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), null, notaryNode.info.notaryIdentity).second
fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notaryNode.info.notaryIdentity).second
}
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
val aliceFuture = runBuyerAndSeller(notaryNode, aliceNode, bobNode, "alice's paper".outputStateAndRef()).sellerResult
@ -335,17 +330,12 @@ class TwoPartyTradeFlowTests {
val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
val bankNode = makeNodeWithTracking(notaryNode.network.myAddress, BOC.name)
val issuer = bankNode.info.legalIdentity.ref(1, 2, 3)
val issuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
mockNet.runNetwork()
notaryNode.internals.ensureRegistered()
val allNodes = listOf(notaryNode, aliceNode, bobNode, bankNode)
allNodes.forEach { node ->
node.database.transaction {
allNodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity -> node.services.identityService.verifyAndRegisterIdentity(identity) }
}
}
mockNet.registerIdentities()
ledger(aliceNode.services, initialiseSerialization = false) {
@ -360,12 +350,12 @@ class TwoPartyTradeFlowTests {
attachment(ByteArrayInputStream(stream.toByteArray()))
}
val bobsFakeCash = fillUpForBuyer(false, issuer, AnonymousParty(bobNode.info.legalIdentity.owningKey),
val bobsFakeCash = fillUpForBuyer(false, issuer, AnonymousParty(bobNode.info.chooseIdentity().owningKey),
notaryNode.info.notaryIdentity).second
val bobsSignedTxns = insertFakeTransactions(bobsFakeCash, bobNode, notaryNode, bankNode)
val alicesFakePaper = aliceNode.database.transaction {
fillUpForSeller(false, issuer, aliceNode.info.legalIdentity,
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), attachmentID, notaryNode.info.notaryIdentity).second
fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), attachmentID, notaryNode.info.notaryIdentity).second
}
val alicesSignedTxns = insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
@ -446,19 +436,12 @@ class TwoPartyTradeFlowTests {
val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
val bankNode = makeNodeWithTracking(notaryNode.network.myAddress, BOC.name)
val issuer = bankNode.info.legalIdentity.ref(1, 2, 3)
val issuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
mockNet.runNetwork()
notaryNode.internals.ensureRegistered()
val allNodes = listOf(notaryNode, aliceNode, bobNode, bankNode)
allNodes.forEach { node ->
node.database.transaction {
allNodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity ->
node.services.identityService.verifyAndRegisterIdentity(identity)
}
}
}
mockNet.registerIdentities()
ledger(aliceNode.services, initialiseSerialization = false) {
// Insert a prospectus type attachment into the commercial paper transaction.
@ -478,8 +461,8 @@ class TwoPartyTradeFlowTests {
insertFakeTransactions(bobsFakeCash, bobNode, notaryNode, bankNode)
val alicesFakePaper = aliceNode.database.transaction {
fillUpForSeller(false, issuer, aliceNode.info.legalIdentity,
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), attachmentID, notaryNode.info.notaryIdentity).second
fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), attachmentID, notaryNode.info.notaryIdentity).second
}
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
@ -556,7 +539,7 @@ class TwoPartyTradeFlowTests {
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.legalIdentity, notaryNode.info, assetToSell, 1000.DOLLARS, anonymous)
val seller = SellerInitiator(buyerNode.info.chooseIdentity(), notaryNode.info, assetToSell, 1000.DOLLARS, anonymous)
val sellerResult = sellerNode.services.startFlow(seller).resultFuture
return RunResult(firstBuyerFiber, sellerResult, seller.stateMachine.id)
}
@ -569,10 +552,10 @@ class TwoPartyTradeFlowTests {
val anonymous: Boolean) : FlowLogic<SignedTransaction>() {
@Suspendable
override fun call(): SignedTransaction {
val me = if (anonymous) {
serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.legalIdentityAndCert, false)
val myParty = if (anonymous) {
serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.chooseIdentityAndCert(), false)
} else {
serviceHub.myInfo.legalIdentityAndCert
serviceHub.myInfo.chooseIdentityAndCert()
}
send(buyer, TestTx(notary.notaryIdentity, price, anonymous))
return subFlow(Seller(
@ -580,7 +563,7 @@ class TwoPartyTradeFlowTests {
notary,
assetToSell,
price,
me))
myParty))
}
}
@ -608,25 +591,20 @@ class TwoPartyTradeFlowTests {
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
val issuer = bankNode.info.legalIdentity.ref(1, 2, 3)
val issuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
mockNet.runNetwork()
notaryNode.internals.ensureRegistered()
// Let the nodes know about each other - normally the network map would handle this
val allNodes = listOf(notaryNode, aliceNode, bobNode, bankNode)
allNodes.forEach { node ->
node.database.transaction {
allNodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity -> node.services.identityService.verifyAndRegisterIdentity(identity) }
}
}
mockNet.registerIdentities()
val bobsBadCash = bobNode.database.transaction {
fillUpForBuyer(bobError, issuer, bobNode.info.legalIdentity,
fillUpForBuyer(bobError, issuer, bobNode.info.chooseIdentity(),
notaryNode.info.notaryIdentity).second
}
val alicesFakePaper = aliceNode.database.transaction {
fillUpForSeller(aliceError, issuer, aliceNode.info.legalIdentity,
fillUpForSeller(aliceError, issuer, aliceNode.info.chooseIdentity(),
1200.DOLLARS `issued by` issuer, null, notaryNode.info.notaryIdentity).second
}
@ -661,10 +639,14 @@ class TwoPartyTradeFlowTests {
val signed = wtxToSign.map {
val id = it.id
val sigs = mutableListOf<TransactionSignature>()
sigs.add(node.services.keyManagementService.sign(SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(node.services.legalIdentityKey).schemeNumberID)), node.services.legalIdentityKey))
val nodeKey = node.info.chooseIdentity().owningKey
sigs.add(node.services.keyManagementService.sign(SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(nodeKey).schemeNumberID)), nodeKey))
sigs.add(notaryNode.services.keyManagementService.sign(SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(notaryNode.services.notaryIdentityKey).schemeNumberID)), notaryNode.services.notaryIdentityKey))
extraSigningNodes.forEach { currentNode ->
sigs.add(currentNode.services.keyManagementService.sign(SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(currentNode.info.legalIdentity.owningKey).schemeNumberID)), currentNode.info.legalIdentity.owningKey))
sigs.add(currentNode.services.keyManagementService.sign(
SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(currentNode.info.chooseIdentity().owningKey).schemeNumberID)),
currentNode.info.chooseIdentity().owningKey)
)
}
SignedTransaction(it, sigs)
}

View File

@ -16,6 +16,7 @@ import net.corda.node.services.network.NetworkMapService
import net.corda.node.services.transactions.SimpleNotaryService
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
import net.corda.testing.getTestPartyAndCertificate
@ -45,7 +46,7 @@ class NotaryChangeTests {
clientNodeA = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress)
clientNodeB = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress)
newNotaryNode = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress, advertisedServices = ServiceInfo(SimpleNotaryService.type))
mockNet.registerIdentities()
mockNet.runNetwork() // Clear network map registration messages
oldNotaryNode.internals.ensureRegistered()
}
@ -133,7 +134,7 @@ class NotaryChangeTests {
}
private fun issueEncumberedState(node: StartedNode<*>, notaryNode: StartedNode<*>): WireTransaction {
val owner = node.info.legalIdentity.ref(0)
val owner = node.info.chooseIdentity().ref(0)
val notary = notaryNode.info.notaryIdentity
val stateA = DummyContract.SingleOwnerState(Random().nextInt(), owner.party)
@ -161,7 +162,7 @@ class NotaryChangeTests {
}
fun issueState(node: StartedNode<*>, notaryNode: StartedNode<*>): StateAndRef<*> {
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.legalIdentity.ref(0))
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.chooseIdentity().ref(0))
val signedByNode = node.services.signInitialTransaction(tx)
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
node.services.recordTransactions(stx)
@ -170,7 +171,7 @@ fun issueState(node: StartedNode<*>, notaryNode: StartedNode<*>): StateAndRef<*>
fun issueMultiPartyState(nodeA: StartedNode<*>, nodeB: StartedNode<*>, notaryNode: StartedNode<*>): StateAndRef<DummyContract.MultiOwnerState> {
val state = TransactionState(DummyContract.MultiOwnerState(0,
listOf(nodeA.info.legalIdentity, nodeB.info.legalIdentity)), DUMMY_PROGRAM_ID, notaryNode.info.notaryIdentity)
listOf(nodeA.info.chooseIdentity(), nodeB.info.chooseIdentity())), DUMMY_PROGRAM_ID, notaryNode.info.notaryIdentity)
val tx = TransactionBuilder(notary = notaryNode.info.notaryIdentity).withItems(state, dummyCommand())
val signedByA = nodeA.services.signInitialTransaction(tx)
val signedByAB = nodeB.services.addSignature(signedByA)
@ -182,7 +183,7 @@ fun issueMultiPartyState(nodeA: StartedNode<*>, nodeB: StartedNode<*>, notaryNod
}
fun issueInvalidState(node: StartedNode<*>, notary: Party): StateAndRef<*> {
val tx = DummyContract.generateInitial(Random().nextInt(), notary, node.info.legalIdentity.ref(0))
val tx = DummyContract.generateInitial(Random().nextInt(), notary, node.info.chooseIdentity().ref(0))
tx.setTimeWindow(Instant.now(), 30.seconds)
val stx = node.services.signInitialTransaction(tx)
node.services.recordTransactions(stx)

View File

@ -77,7 +77,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
val dataSourceProps = makeTestDataSourceProperties()
val databaseProperties = makeTestDatabaseProperties()
database = configureDatabase(dataSourceProps, databaseProperties, createIdentityService = ::makeTestIdentityService)
val identityService = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
val identityService = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
val kms = MockKeyManagementService(identityService, ALICE_KEY)
database.transaction {
@ -277,7 +277,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
database.transaction {
apply {
val freshKey = services.keyManagementService.freshKey()
val state = TestState(FlowLogicRefFactoryImpl.createForRPC(TestFlowLogic::class.java, increment), instant, services.myInfo.legalIdentity)
val state = TestState(FlowLogicRefFactoryImpl.createForRPC(TestFlowLogic::class.java, increment), instant, services.myInfo.chooseIdentity())
val builder = TransactionBuilder(null).apply {
addOutputState(state, DUMMY_PROGRAM_ID, DUMMY_NOTARY)
addCommand(Command(), freshKey)

View File

@ -22,6 +22,7 @@ import net.corda.node.services.statemachine.StateMachineManager
import net.corda.node.services.transactions.ValidatingNotaryService
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.chooseIdentity
import net.corda.testing.dummyCommand
import net.corda.testing.node.MockNetwork
import org.junit.After
@ -62,14 +63,14 @@ class ScheduledFlowTests {
@Suspendable
override fun call() {
val scheduledState = ScheduledState(serviceHub.clock.instant(),
serviceHub.myInfo.legalIdentity, destination)
serviceHub.myInfo.chooseIdentity(), destination)
val notary = serviceHub.networkMapCache.getAnyNotary()
val builder = TransactionBuilder(notary)
.addOutputState(scheduledState, DUMMY_PROGRAM_ID)
.addCommand(dummyCommand(serviceHub.legalIdentityKey))
.addCommand(dummyCommand(ourIdentity.owningKey))
val tx = serviceHub.signInitialTransaction(builder)
subFlow(FinalityFlow(tx, setOf(serviceHub.myInfo.legalIdentity)))
subFlow(FinalityFlow(tx, setOf(serviceHub.myInfo.chooseIdentity())))
}
}
@ -80,7 +81,7 @@ class ScheduledFlowTests {
val state = serviceHub.toStateAndRef<ScheduledState>(stateRef)
val scheduledState = state.state.data
// Only run flow over states originating on this node
if (scheduledState.source != serviceHub.myInfo.legalIdentity) {
if (scheduledState.source != serviceHub.myInfo.chooseIdentity()) {
return
}
require(!scheduledState.processed) { "State should not have been previously processed" }
@ -89,7 +90,7 @@ class ScheduledFlowTests {
val builder = TransactionBuilder(notary)
.addInputState(state)
.addOutputState(newStateOutput, DUMMY_PROGRAM_ID)
.addCommand(dummyCommand(serviceHub.legalIdentityKey))
.addCommand(dummyCommand(serviceHub.myInfo.chooseIdentity().owningKey))
val tx = serviceHub.signInitialTransaction(builder)
subFlow(FinalityFlow(tx, setOf(scheduledState.source, scheduledState.destination)))
}
@ -126,7 +127,7 @@ class ScheduledFlowTests {
countScheduledFlows++
}
}
nodeA.services.startFlow(InsertInitialStateFlow(nodeB.info.legalIdentity))
nodeA.services.startFlow(InsertInitialStateFlow(nodeB.info.chooseIdentity()))
mockNet.waitQuiescent()
val stateFromA = nodeA.database.transaction {
nodeA.services.vaultQueryService.queryBy<ScheduledState>().states.single()
@ -144,8 +145,8 @@ class ScheduledFlowTests {
val N = 100
val futures = mutableListOf<CordaFuture<*>>()
for (i in 0..N - 1) {
futures.add(nodeA.services.startFlow(InsertInitialStateFlow(nodeB.info.legalIdentity)).resultFuture)
futures.add(nodeB.services.startFlow(InsertInitialStateFlow(nodeA.info.legalIdentity)).resultFuture)
futures.add(nodeA.services.startFlow(InsertInitialStateFlow(nodeB.info.chooseIdentity())).resultFuture)
futures.add(nodeB.services.startFlow(InsertInitialStateFlow(nodeA.info.chooseIdentity())).resultFuture)
}
mockNet.waitQuiescent()

View File

@ -30,6 +30,8 @@ import net.corda.testing.ALICE
import net.corda.testing.BOB
import net.corda.testing.CHARLIE
import net.corda.testing.DUMMY_MAP
import net.corda.testing.chooseIdentity
import net.corda.testing.chooseIdentityAndCert
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetwork.MockNode
import org.assertj.core.api.Assertions.assertThat
@ -203,7 +205,7 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
}
private fun StartedNode<*>.identityQuery(): NodeInfo? {
val request = QueryIdentityRequest(info.legalIdentityAndCert, network.myAddress)
val request = QueryIdentityRequest(services.myInfo.chooseIdentityAndCert(), network.myAddress)
val response = services.networkService.sendRequest<QueryIdentityResponse>(QUERY_TOPIC, request, mapServiceNode.network.myAddress)
mockNet.runNetwork()
return response.getOrThrow().node
@ -221,7 +223,7 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
}
val expires = Instant.now() + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
val nodeRegistration = NodeRegistration(info, distinctSerial, addOrRemove, expires)
val request = RegistrationRequest(nodeRegistration.toWire(services.keyManagementService, services.legalIdentityKey), network.myAddress)
val request = RegistrationRequest(nodeRegistration.toWire(services.keyManagementService, info.chooseIdentity().owningKey), network.myAddress)
val response = services.networkService.sendRequest<RegistrationResponse>(REGISTER_TOPIC, request, mapServiceNode.network.myAddress)
mockNet.runNetwork()
return response

View File

@ -16,7 +16,6 @@ import net.corda.node.utilities.X509Utilities
import net.corda.testing.*
import org.junit.Test
import java.security.cert.CertificateFactory
import javax.security.auth.x500.X500Principal
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertNull
@ -27,7 +26,7 @@ import kotlin.test.assertNull
class InMemoryIdentityServiceTests {
@Test
fun `get all identities`() {
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
// Nothing registered, so empty set
assertNull(service.getAllIdentities().firstOrNull())
@ -45,7 +44,7 @@ class InMemoryIdentityServiceTests {
@Test
fun `get identity by key`() {
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
assertNull(service.partyFromKey(ALICE_PUBKEY))
service.verifyAndRegisterIdentity(ALICE_IDENTITY)
assertEquals(ALICE, service.partyFromKey(ALICE_PUBKEY))
@ -54,14 +53,13 @@ class InMemoryIdentityServiceTests {
@Test
fun `get identity by name with no registered identities`() {
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
assertNull(service.partyFromX500Name(ALICE.name))
}
@Test
fun `get identity by substring match`() {
val trustRoot = DUMMY_CA
val service = InMemoryIdentityService(trustRoot = trustRoot.certificate)
val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
service.verifyAndRegisterIdentity(ALICE_IDENTITY)
service.verifyAndRegisterIdentity(BOB_IDENTITY)
val alicente = getTestPartyAndCertificate(CordaX500Name(organisation = "Alicente Worldwide", locality = "London", country = "GB"), generateKeyPair().public)
@ -73,7 +71,7 @@ class InMemoryIdentityServiceTests {
@Test
fun `get identity by name`() {
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
val identities = listOf("Org A", "Org B", "Org C")
.map { getTestPartyAndCertificate(CordaX500Name(organisation = it, locality = "London", country = "GB"), generateKeyPair().public) }
assertNull(service.partyFromX500Name(identities.first().name))
@ -90,7 +88,7 @@ class InMemoryIdentityServiceTests {
val rootKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val rootCert = X509Utilities.createSelfSignedCACertificate(ALICE.name, rootKey)
val txKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
// TODO: Generate certificate with an EdDSA key rather than ECDSA
val identity = Party(rootCert.cert)
val txIdentity = AnonymousParty(txKey.public)
@ -107,12 +105,11 @@ class InMemoryIdentityServiceTests {
*/
@Test
fun `get anonymous identity by key`() {
val trustRoot = DUMMY_CA
val (alice, aliceTxIdentity) = createParty(ALICE.name, trustRoot)
val (_, bobTxIdentity) = createParty(ALICE.name, trustRoot)
val (alice, aliceTxIdentity) = createParty(ALICE.name, DEV_CA)
val (_, bobTxIdentity) = createParty(ALICE.name, DEV_CA)
// Now we have identities, construct the service and let it know about both
val service = InMemoryIdentityService(setOf(alice), emptySet(), trustRoot.certificate.cert)
val service = InMemoryIdentityService(setOf(alice), emptySet(), DEV_TRUST_ROOT)
service.verifyAndRegisterIdentity(aliceTxIdentity)
var actual = service.certificateFromKey(aliceTxIdentity.party.owningKey)
@ -131,12 +128,11 @@ class InMemoryIdentityServiceTests {
@Test
fun `assert ownership`() {
withTestSerialization {
val trustRoot = DUMMY_CA
val (alice, anonymousAlice) = createParty(ALICE.name, trustRoot)
val (bob, anonymousBob) = createParty(BOB.name, trustRoot)
val (alice, anonymousAlice) = createParty(ALICE.name, DEV_CA)
val (bob, anonymousBob) = createParty(BOB.name, DEV_CA)
// Now we have identities, construct the service and let it know about both
val service = InMemoryIdentityService(setOf(alice, bob), emptySet(), trustRoot.certificate.cert)
val service = InMemoryIdentityService(setOf(alice, bob), emptySet(), DEV_TRUST_ROOT)
service.verifyAndRegisterIdentity(anonymousAlice)
service.verifyAndRegisterIdentity(anonymousBob)
@ -152,8 +148,8 @@ class InMemoryIdentityServiceTests {
}
assertFailsWith<IllegalArgumentException> {
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded)
val subject = CordaX500Name.build(X500Principal(trustRoot.certificate.subject.encoded))
val owningKey = Crypto.decodePublicKey(DEV_CA.certificate.subjectPublicKeyInfo.encoded)
val subject = CordaX500Name.build(DEV_CA.certificate.cert.subjectX500Principal)
service.assertOwnership(Party(subject, owningKey), anonymousAlice.party.anonymise())
}
}
@ -175,7 +171,7 @@ class InMemoryIdentityServiceTests {
@Test
fun `deanonymising a well known identity`() {
val expected = ALICE
val actual = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate).partyFromAnonymous(expected)
val actual = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT).partyFromAnonymous(expected)
assertEquals(expected, actual)
}
}

View File

@ -5,6 +5,7 @@ import net.corda.core.node.services.ServiceInfo
import net.corda.core.utilities.getOrThrow
import net.corda.testing.ALICE
import net.corda.testing.BOB
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
@ -41,16 +42,16 @@ class NetworkMapCacheTest {
val entropy = BigInteger.valueOf(24012017L)
val nodeA = mockNet.createNode(nodeFactory = MockNetwork.DefaultFactory, legalName = ALICE.name, entropyRoot = entropy, advertisedServices = ServiceInfo(NetworkMapService.type))
val nodeB = mockNet.createNode(nodeFactory = MockNetwork.DefaultFactory, legalName = BOB.name, entropyRoot = entropy, advertisedServices = ServiceInfo(NetworkMapService.type))
assertEquals(nodeA.info.legalIdentity, nodeB.info.legalIdentity)
assertEquals(nodeA.info.chooseIdentity(), nodeB.info.chooseIdentity())
mockNet.runNetwork()
// Node A currently knows only about itself, so this returns node A
assertEquals(nodeA.services.networkMapCache.getNodeByLegalIdentityKey(nodeA.info.legalIdentity.owningKey), nodeA.info)
assertEquals(nodeA.services.networkMapCache.getNodesByLegalIdentityKey(nodeA.info.chooseIdentity().owningKey).singleOrNull(), nodeA.info)
nodeA.services.networkMapCache.addNode(nodeB.info)
// The details of node B write over those for node A
assertEquals(nodeA.services.networkMapCache.getNodeByLegalIdentityKey(nodeA.info.legalIdentity.owningKey), nodeB.info)
assertEquals(nodeA.services.networkMapCache.getNodesByLegalIdentityKey(nodeA.info.chooseIdentity().owningKey).singleOrNull(), nodeB.info)
}
@Test
@ -62,7 +63,7 @@ class NetworkMapCacheTest {
val expected = n1.info
mockNet.runNetwork()
val actual = n0.database.transaction { node0Cache.getNodeByLegalIdentity(n1.info.legalIdentity) }
val actual = n0.database.transaction { node0Cache.getNodeByLegalIdentity(n1.info.chooseIdentity()) }
assertEquals(expected, actual)
// TODO: Should have a test case with anonymous lookup
@ -73,14 +74,16 @@ class NetworkMapCacheTest {
val nodes = mockNet.createSomeNodes(1)
val n0 = nodes.mapNode
val n1 = nodes.partyNodes[0]
val n0Identity = n0.info.chooseIdentity()
val n1Identity = n1.info.chooseIdentity()
val node0Cache = n0.services.networkMapCache as PersistentNetworkMapCache
mockNet.runNetwork()
n0.database.transaction {
assertThat(node0Cache.getNodeByLegalIdentity(n1.info.legalIdentity) != null)
assertThat(node0Cache.getNodeByLegalIdentity(n1Identity) != null)
node0Cache.removeNode(n1.info)
assertThat(node0Cache.getNodeByLegalIdentity(n1.info.legalIdentity) == null)
assertThat(node0Cache.getNodeByLegalIdentity(n0.info.legalIdentity) != null)
assertThat(node0Cache.getNodeByLegalName(n1.info.legalIdentity.name) == null)
assertThat(node0Cache.getNodeByLegalIdentity(n1Identity) == null)
assertThat(node0Cache.getNodeByLegalIdentity(n0Identity) != null)
assertThat(node0Cache.getNodeByLegalName(n1Identity.name) == null)
}
}
}

View File

@ -37,7 +37,7 @@ class PersistentIdentityServiceTests {
@Before
fun setup() {
val databaseAndServices = MockServices.makeTestDatabaseAndMockServices(keys = emptyList(), createIdentityService = { PersistentIdentityService(trustRoot = DUMMY_CA.certificate) })
val databaseAndServices = MockServices.makeTestDatabaseAndMockServices(keys = emptyList(), createIdentityService = { PersistentIdentityService(trustRoot = DEV_TRUST_ROOT) })
database = databaseAndServices.first
services = databaseAndServices.second
identityService = services.identityService
@ -152,9 +152,8 @@ class PersistentIdentityServiceTests {
*/
@Test
fun `get anonymous identity by key`() {
val trustRoot = DUMMY_CA
val (alice, aliceTxIdentity) = createParty(ALICE.name, trustRoot)
val (_, bobTxIdentity) = createParty(ALICE.name, trustRoot)
val (alice, aliceTxIdentity) = createParty(ALICE.name, DEV_CA)
val (_, bobTxIdentity) = createParty(ALICE.name, DEV_CA)
// Now we have identities, construct the service and let it know about both
database.transaction {
@ -186,9 +185,8 @@ class PersistentIdentityServiceTests {
@Test
fun `assert ownership`() {
withTestSerialization {
val trustRoot = DUMMY_CA
val (alice, anonymousAlice) = createParty(ALICE.name, trustRoot)
val (bob, anonymousBob) = createParty(BOB.name, trustRoot)
val (alice, anonymousAlice) = createParty(ALICE.name, DEV_CA)
val (bob, anonymousBob) = createParty(BOB.name, DEV_CA)
database.transaction {
// Now we have identities, construct the service and let it know about both
@ -213,9 +211,9 @@ class PersistentIdentityServiceTests {
}
assertFailsWith<IllegalArgumentException> {
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded)
val owningKey = Crypto.decodePublicKey(DEV_CA.certificate.subjectPublicKeyInfo.encoded)
database.transaction {
val subject = CordaX500Name.build(X500Principal(trustRoot.certificate.subject.encoded))
val subject = CordaX500Name.build(DEV_CA.certificate.cert.subjectX500Principal)
identityService.assertOwnership(Party(subject, owningKey), anonymousAlice.party.anonymise())
}
}
@ -224,9 +222,8 @@ class PersistentIdentityServiceTests {
@Test
fun `Test Persistence`() {
val trustRoot = DUMMY_CA
val (alice, anonymousAlice) = createParty(ALICE.name, trustRoot)
val (bob, anonymousBob) = createParty(BOB.name, trustRoot)
val (alice, anonymousAlice) = createParty(ALICE.name, DEV_CA)
val (bob, anonymousBob) = createParty(BOB.name, DEV_CA)
database.transaction {
// Register well known identities
@ -239,7 +236,7 @@ class PersistentIdentityServiceTests {
// Create new identity service mounted onto same DB
val newPersistentIdentityService = database.transaction {
PersistentIdentityService(trustRoot = DUMMY_CA.certificate)
PersistentIdentityService(trustRoot = DEV_TRUST_ROOT)
}
database.transaction {

View File

@ -14,6 +14,7 @@ import net.corda.testing.ALICE
import net.corda.testing.BOB
import net.corda.testing.CHARLIE
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.node.NodeBasedTest
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
@ -32,7 +33,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
nodes.forEach { it.internals.nodeReadyFuture.get() } // Need to wait for network map registration, as these tests are ran without waiting.
nodes.forEach {
infos.add(it.info)
addressesMap[it.info.legalIdentity.name] = it.info.addresses[0]
addressesMap[it.info.chooseIdentity().name] = it.info.addresses[0]
it.dispose() // We want them to communicate with NetworkMapService to save data to cache.
}
}
@ -42,10 +43,10 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
val alice = startNodesWithPort(listOf(ALICE), noNetworkMap = true)[0]
val netCache = alice.services.networkMapCache as PersistentNetworkMapCache
alice.database.transaction {
val res = netCache.getNodeByLegalIdentity(alice.info.legalIdentity)
val res = netCache.getNodeByLegalIdentity(alice.info.chooseIdentity())
assertEquals(alice.info, res)
val res2 = netCache.getNodeByLegalName(DUMMY_NOTARY.name)
assertEquals(infos.filter { it.legalIdentity.name == DUMMY_NOTARY.name }.singleOrNull(), res2)
assertEquals(infos.filter { DUMMY_NOTARY.name in it.legalIdentitiesAndCerts.map { it.name } }.singleOrNull(), res2)
}
}
@ -66,7 +67,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
assert(NetworkMapService.type !in alice.info.advertisedServices.map { it.info.type })
assertEquals(NullNetworkMapService, alice.inNodeNetworkMapService)
assertEquals(infos.size, partyNodes.size)
assertEquals(infos.map { it.legalIdentity }.toSet(), partyNodes.map { it.legalIdentity }.toSet())
assertEquals(infos.flatMap { it.legalIdentities }.toSet(), partyNodes.flatMap { it.legalIdentities }.toSet())
}
@Test
@ -78,7 +79,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
nodes.forEach {
val partyNodes = it.services.networkMapCache.partyNodes
assertEquals(infos.size, partyNodes.size)
assertEquals(infos.map { it.legalIdentity }.toSet(), partyNodes.map { it.legalIdentity }.toSet())
assertEquals(infos.flatMap { it.legalIdentities }.toSet(), partyNodes.flatMap { it.legalIdentities }.toSet())
}
checkConnectivity(nodes)
}
@ -92,7 +93,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
nodes.forEach {
val partyNodes = it.services.networkMapCache.partyNodes
assertEquals(infos.size, partyNodes.size)
assertEquals(infos.map { it.legalIdentity }.toSet(), partyNodes.map { it.legalIdentity }.toSet())
assertEquals(infos.flatMap { it.legalIdentities }.toSet(), partyNodes.flatMap { it.legalIdentities }.toSet())
}
checkConnectivity(nodes)
}
@ -115,20 +116,20 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
// Start 2 nodes pointing at network map, but don't start network map service.
val otherNodes = startNodesWithPort(parties, noNetworkMap = false)
otherNodes.forEach { node ->
assert(infos.any { it.legalIdentity == node.info.legalIdentity })
assert(infos.any { it.legalIdentitiesAndCerts.toSet() == node.info.legalIdentitiesAndCerts.toSet() })
}
// 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 {
assert(charlie.info.legalIdentity !in it.services.networkMapCache.partyNodes.map { it.legalIdentity })
assert(charlie.info.chooseIdentity() !in it.services.networkMapCache.partyNodes.flatMap { it.legalIdentities })
}
// Start Network Map and see that charlie node appears in caches.
val nms = startNodesWithPort(listOf(DUMMY_NOTARY), noNetworkMap = false)[0]
nms.internals.startupComplete.get()
assert(nms.inNodeNetworkMapService != NullNetworkMapService)
assert(infos.any {it.legalIdentity == nms.info.legalIdentity})
assert(infos.any { it.legalIdentities.toSet() == nms.info.legalIdentities.toSet() })
otherNodes.forEach {
assert(nms.info.legalIdentity in it.services.networkMapCache.partyNodes.map { it.legalIdentity })
assert(nms.info.chooseIdentity() in it.services.networkMapCache.partyNodes.map { it.chooseIdentity() })
}
charlie.internals.nodeReadyFuture.get() // Finish registration.
checkConnectivity(listOf(otherNodes[0], nms)) // Checks connectivity from A to NMS.
@ -136,7 +137,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
val cacheB = otherNodes[1].services.networkMapCache.partyNodes
val cacheC = charlie.services.networkMapCache.partyNodes
assertEquals(4, cacheC.size) // Charlie fetched data from NetworkMap
assert(charlie.info.legalIdentity in cacheB.map { it.legalIdentity }) // Other nodes also fetched data from Network Map with node C.
assert(charlie.info.chooseIdentity() in cacheB.map { it.chooseIdentity() }) // Other nodes also fetched data from Network Map with node C.
assertEquals(cacheA.toSet(), cacheB.toSet())
assertEquals(cacheA.toSet(), cacheC.toSet())
}
@ -163,7 +164,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
nodes.forEach { node1 ->
nodes.forEach { node2 ->
node2.internals.registerInitiatedFlow(SendBackFlow::class.java)
val resultFuture = node1.services.startFlow(SendFlow(node2.info.legalIdentity)).resultFuture
val resultFuture = node1.services.startFlow(SendFlow(node2.info.chooseIdentity())).resultFuture
assertThat(resultFuture.getOrThrow()).isEqualTo("Hello!")
}
}

View File

@ -17,6 +17,7 @@ import net.corda.node.internal.StartedNode
import net.corda.node.services.NotifyTransactionHandler
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.MEGA_CORP
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
@ -45,8 +46,8 @@ class DataVendingServiceTests {
val nodes = mockNet.createSomeNodes(2)
val vaultServiceNode = nodes.partyNodes[0]
val registerNode = nodes.partyNodes[1]
val beneficiary = vaultServiceNode.info.legalIdentity
val deposit = registerNode.info.legalIdentity.ref(1)
val beneficiary = vaultServiceNode.info.chooseIdentity()
val deposit = registerNode.info.chooseIdentity().ref(1)
mockNet.runNetwork()
// Generate an issuance transaction
@ -75,7 +76,7 @@ class DataVendingServiceTests {
val nodes = mockNet.createSomeNodes(2)
val vaultServiceNode = nodes.partyNodes[0]
val registerNode = nodes.partyNodes[1]
val beneficiary = vaultServiceNode.info.legalIdentity
val beneficiary = vaultServiceNode.info.chooseIdentity()
val deposit = MEGA_CORP.ref(1)
mockNet.runNetwork()
@ -97,7 +98,7 @@ class DataVendingServiceTests {
private fun StartedNode<*>.sendNotifyTx(tx: SignedTransaction, walletServiceNode: StartedNode<*>) {
walletServiceNode.internals.registerInitiatedFlow(InitiateNotifyTxFlow::class.java)
services.startFlow(NotifyTxFlow(walletServiceNode.info.legalIdentity, tx))
services.startFlow(NotifyTxFlow(walletServiceNode.info.chooseIdentity(), tx))
mockNet.runNetwork()
}

View File

@ -94,14 +94,7 @@ class FlowFrameworkTests {
mockNet.runNetwork()
// We don't create a network map, so manually handle registrations
val nodes = listOf(node1, node2, notary1, notary2)
nodes.forEach { node ->
node.database.transaction {
nodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity ->
node.services.identityService.verifyAndRegisterIdentity(identity)
}
}
}
mockNet.registerIdentities()
}
@After
@ -128,7 +121,7 @@ class FlowFrameworkTests {
@Test
fun `exception while fiber suspended`() {
node2.registerFlowFactory(ReceiveFlow::class) { SendFlow("Hello", it) }
val flow = ReceiveFlow(node2.info.legalIdentity)
val flow = ReceiveFlow(node2.info.chooseIdentity())
val fiber = node1.services.startFlow(flow) as FlowStateMachineImpl
// Before the flow runs change the suspend action to throw an exception
val exceptionDuringSuspend = Exception("Thrown during suspend")
@ -147,7 +140,7 @@ class FlowFrameworkTests {
@Test
fun `flow restarted just after receiving payload`() {
node2.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() }
node1.services.startFlow(SendFlow("Hello", node2.info.legalIdentity))
node1.services.startFlow(SendFlow("Hello", node2.info.chooseIdentity()))
// We push through just enough messages to get only the payload sent
node2.pumpReceive()
@ -199,7 +192,7 @@ class FlowFrameworkTests {
@Test
fun `flow loaded from checkpoint will respond to messages from before start`() {
node1.registerFlowFactory(ReceiveFlow::class) { SendFlow("Hello", it) }
node2.services.startFlow(ReceiveFlow(node1.info.legalIdentity).nonTerminating()) // Prepare checkpointed receive flow
node2.services.startFlow(ReceiveFlow(node1.info.chooseIdentity()).nonTerminating()) // Prepare checkpointed receive flow
// Make sure the add() has finished initial processing.
node2.smm.executor.flush()
node2.internals.disableDBCloseOnStop()
@ -221,7 +214,7 @@ class FlowFrameworkTests {
mockNet.runNetwork()
// Kick off first send and receive
node2.services.startFlow(PingPongFlow(node3.info.legalIdentity, payload))
node2.services.startFlow(PingPongFlow(node3.info.chooseIdentity(), payload))
node2.database.transaction {
assertEquals(1, node2.checkpointStorage.checkpoints().size)
}
@ -266,7 +259,7 @@ class FlowFrameworkTests {
node2.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() }
node3.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() }
val payload = "Hello World"
node1.services.startFlow(SendFlow(payload, node2.info.legalIdentity, node3.info.legalIdentity))
node1.services.startFlow(SendFlow(payload, node2.info.chooseIdentity(), node3.info.chooseIdentity()))
mockNet.runNetwork()
val node2Flow = node2.getSingleFlow<ReceiveFlow>().first
val node3Flow = node3.getSingleFlow<ReceiveFlow>().first
@ -299,7 +292,7 @@ class FlowFrameworkTests {
val node3Payload = "Test 2"
node2.registerFlowFactory(ReceiveFlow::class) { SendFlow(node2Payload, it) }
node3.registerFlowFactory(ReceiveFlow::class) { SendFlow(node3Payload, it) }
val multiReceiveFlow = ReceiveFlow(node2.info.legalIdentity, node3.info.legalIdentity).nonTerminating()
val multiReceiveFlow = ReceiveFlow(node2.info.chooseIdentity(), node3.info.chooseIdentity()).nonTerminating()
node1.services.startFlow(multiReceiveFlow)
node1.internals.acceptableLiveFiberCountOnStop = 1
mockNet.runNetwork()
@ -324,7 +317,7 @@ class FlowFrameworkTests {
@Test
fun `both sides do a send as their first IO request`() {
node2.registerFlowFactory(PingPongFlow::class) { PingPongFlow(it, 20L) }
node1.services.startFlow(PingPongFlow(node2.info.legalIdentity, 10L))
node1.services.startFlow(PingPongFlow(node2.info.chooseIdentity(), 10L))
mockNet.runNetwork()
assertSessionTransfers(
@ -347,13 +340,13 @@ class FlowFrameworkTests {
notary1.info.notaryIdentity)).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.legalIdentity))
val flow = node1.services.startFlow(CashPaymentFlow(500.DOLLARS, node2.info.chooseIdentity()))
mockNet.runNetwork()
flow.resultFuture.getOrThrow()
}
val endpoint = mockNet.messagingNetwork.endpoint(notary1.network.myAddress as InMemoryMessagingNetwork.PeerHandle)!!
val party1Info = notary1.services.networkMapCache.getPartyInfo(notary1.info.notaryIdentity)!!
assertTrue(party1Info is PartyInfo.Service)
assertTrue(party1Info is PartyInfo.DistributedNode)
val notary1Address: MessageRecipients = endpoint.getAddressOfParty(notary1.services.networkMapCache.getPartyInfo(notary1.info.notaryIdentity)!!)
assertThat(notary1Address).isInstanceOf(InMemoryMessagingNetwork.ServiceHandle::class.java)
assertEquals(notary1Address, endpoint.getAddressOfParty(notary2.services.networkMapCache.getPartyInfo(notary2.info.notaryIdentity)!!))
@ -396,7 +389,7 @@ class FlowFrameworkTests {
@Test
fun `other side ends before doing expected send`() {
node2.registerFlowFactory(ReceiveFlow::class) { NoOpFlow() }
val resultFuture = node1.services.startFlow(ReceiveFlow(node2.info.legalIdentity)).resultFuture
val resultFuture = node1.services.startFlow(ReceiveFlow(node2.info.chooseIdentity())).resultFuture
mockNet.runNetwork()
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
resultFuture.getOrThrow()
@ -409,7 +402,7 @@ class FlowFrameworkTests {
val sessionEndReceived = Semaphore(0)
receivedSessionMessagesObservable().filter { it.message is SessionEnd }.subscribe { sessionEndReceived.release() }
val resultFuture = node1.services.startFlow(
WaitForOtherSideEndBeforeSendAndReceive(node2.info.legalIdentity, sessionEndReceived)).resultFuture
WaitForOtherSideEndBeforeSendAndReceive(node2.info.chooseIdentity(), sessionEndReceived)).resultFuture
mockNet.runNetwork()
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
resultFuture.getOrThrow()
@ -436,7 +429,7 @@ class FlowFrameworkTests {
}
val erroringFlowSteps = erroringFlowFuture.flatMap { it.progressSteps }
val receiveFlow = ReceiveFlow(node2.info.legalIdentity)
val receiveFlow = ReceiveFlow(node2.info.chooseIdentity())
val receiveFlowSteps = receiveFlow.progressSteps
val receiveFlowResult = node1.services.startFlow(receiveFlow).resultFuture
@ -470,7 +463,7 @@ class FlowFrameworkTests {
}
val erroringFlowSteps = erroringFlow.flatMap { it.progressSteps }
val receivingFiber = node1.services.startFlow(ReceiveFlow(node2.info.legalIdentity)) as FlowStateMachineImpl
val receivingFiber = node1.services.startFlow(ReceiveFlow(node2.info.chooseIdentity())) as FlowStateMachineImpl
mockNet.runNetwork()
@ -504,8 +497,8 @@ class FlowFrameworkTests {
mockNet.runNetwork()
node3.registerFlowFactory(ReceiveFlow::class) { ExceptionFlow { MyFlowException("Chain") } }
node2.registerFlowFactory(ReceiveFlow::class) { ReceiveFlow(node3.info.legalIdentity) }
val receivingFiber = node1.services.startFlow(ReceiveFlow(node2.info.legalIdentity))
node2.registerFlowFactory(ReceiveFlow::class) { ReceiveFlow(node3.info.chooseIdentity()) }
val receivingFiber = node1.services.startFlow(ReceiveFlow(node2.info.chooseIdentity()))
mockNet.runNetwork()
assertThatExceptionOfType(MyFlowException::class.java)
.isThrownBy { receivingFiber.resultFuture.getOrThrow() }
@ -524,7 +517,7 @@ class FlowFrameworkTests {
.map { it.stateMachine }
node3.registerFlowFactory(ReceiveFlow::class) { ExceptionFlow { MyFlowException("Nothing useful") } }
val node1Fiber = node1.services.startFlow(ReceiveFlow(node2.info.legalIdentity, node3.info.legalIdentity)) as FlowStateMachineImpl
val node1Fiber = node1.services.startFlow(ReceiveFlow(node2.info.chooseIdentity(), node3.info.chooseIdentity())) as FlowStateMachineImpl
mockNet.runNetwork()
// Node 1 will terminate with the error it received from node 3 but it won't propagate that to node 2 (as it's
@ -576,7 +569,7 @@ class FlowFrameworkTests {
}
node2.registerFlowFactory(AskForExceptionFlow::class) { ConditionalExceptionFlow(it, "Hello") }
val resultFuture = node1.services.startFlow(RetryOnExceptionFlow(node2.info.legalIdentity)).resultFuture
val resultFuture = node1.services.startFlow(RetryOnExceptionFlow(node2.info.chooseIdentity())).resultFuture
mockNet.runNetwork()
assertThat(resultFuture.getOrThrow()).isEqualTo("Hello")
}
@ -584,7 +577,7 @@ class FlowFrameworkTests {
@Test
fun `serialisation issue in counterparty`() {
node2.registerFlowFactory(ReceiveFlow::class) { SendFlow(NonSerialisableData(1), it) }
val result = node1.services.startFlow(ReceiveFlow(node2.info.legalIdentity)).resultFuture
val result = node1.services.startFlow(ReceiveFlow(node2.info.chooseIdentity())).resultFuture
mockNet.runNetwork()
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
result.getOrThrow()
@ -596,7 +589,7 @@ class FlowFrameworkTests {
node2.registerFlowFactory(ReceiveFlow::class) {
ExceptionFlow { NonSerialisableFlowException(NonSerialisableData(1)) }
}
val result = node1.services.startFlow(ReceiveFlow(node2.info.legalIdentity)).resultFuture
val result = node1.services.startFlow(ReceiveFlow(node2.info.chooseIdentity())).resultFuture
mockNet.runNetwork()
assertThatExceptionOfType(FlowException::class.java).isThrownBy {
result.getOrThrow()
@ -607,13 +600,13 @@ class FlowFrameworkTests {
fun `wait for transaction`() {
val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity)
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
.addCommand(dummyCommand(node1.services.legalIdentityKey))
.addCommand(dummyCommand(node1.info.chooseIdentity().owningKey))
val stx = node1.services.signInitialTransaction(ptx)
val committerFiber = node1.registerFlowFactory(WaitingFlows.Waiter::class) {
WaitingFlows.Committer(it)
}.map { it.stateMachine }
val waiterStx = node2.services.startFlow(WaitingFlows.Waiter(stx, node1.info.legalIdentity)).resultFuture
val waiterStx = node2.services.startFlow(WaitingFlows.Waiter(stx, node1.info.chooseIdentity())).resultFuture
mockNet.runNetwork()
assertThat(waiterStx.getOrThrow()).isEqualTo(committerFiber.getOrThrow().resultFuture.getOrThrow())
}
@ -628,7 +621,7 @@ class FlowFrameworkTests {
node1.registerFlowFactory(WaitingFlows.Waiter::class) {
WaitingFlows.Committer(it) { throw Exception("Error") }
}
val waiter = node2.services.startFlow(WaitingFlows.Waiter(stx, node1.info.legalIdentity)).resultFuture
val waiter = node2.services.startFlow(WaitingFlows.Waiter(stx, node1.info.chooseIdentity())).resultFuture
mockNet.runNetwork()
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
waiter.getOrThrow()
@ -639,13 +632,13 @@ class FlowFrameworkTests {
fun `verify vault query service is tokenizable by force checkpointing within a flow`() {
val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity)
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
.addCommand(dummyCommand(node1.services.legalIdentityKey))
.addCommand(dummyCommand(node1.info.chooseIdentity().owningKey))
val stx = node1.services.signInitialTransaction(ptx)
node1.registerFlowFactory(VaultQueryFlow::class) {
WaitingFlows.Committer(it)
}
val result = node2.services.startFlow(VaultQueryFlow(stx, node1.info.legalIdentity)).resultFuture
val result = node2.services.startFlow(VaultQueryFlow(stx, node1.info.chooseIdentity())).resultFuture
mockNet.runNetwork()
assertThat(result.getOrThrow()).isEmpty()
@ -654,14 +647,14 @@ class FlowFrameworkTests {
@Test
fun `customised client flow`() {
val receiveFlowFuture = node2.registerFlowFactory(SendFlow::class) { ReceiveFlow(it) }
node1.services.startFlow(CustomSendFlow("Hello", node2.info.legalIdentity)).resultFuture
node1.services.startFlow(CustomSendFlow("Hello", node2.info.chooseIdentity())).resultFuture
mockNet.runNetwork()
assertThat(receiveFlowFuture.getOrThrow().receivedPayloads).containsOnly("Hello")
}
@Test
fun `customised client flow which has annotated @InitiatingFlow again`() {
val result = node1.services.startFlow(IncorrectCustomSendFlow("Hello", node2.info.legalIdentity)).resultFuture
val result = node1.services.startFlow(IncorrectCustomSendFlow("Hello", node2.info.chooseIdentity())).resultFuture
mockNet.runNetwork()
assertThatExceptionOfType(IllegalArgumentException::class.java).isThrownBy {
result.getOrThrow()
@ -671,7 +664,7 @@ class FlowFrameworkTests {
@Test
fun `upgraded initiating flow`() {
node2.registerFlowFactory(UpgradedFlow::class, initiatedFlowVersion = 1) { SendFlow("Old initiated", it) }
val result = node1.services.startFlow(UpgradedFlow(node2.info.legalIdentity)).resultFuture
val result = node1.services.startFlow(UpgradedFlow(node2.info.chooseIdentity())).resultFuture
mockNet.runNetwork()
assertThat(receivedSessionMessages).startsWith(
node1 sent sessionInit(UpgradedFlow::class, flowVersion = 2) to node2,
@ -685,19 +678,19 @@ class FlowFrameworkTests {
@Test
fun `upgraded initiated flow`() {
node2.registerFlowFactory(SendFlow::class, initiatedFlowVersion = 2) { UpgradedFlow(it) }
val initiatingFlow = SendFlow("Old initiating", node2.info.legalIdentity)
val initiatingFlow = SendFlow("Old initiating", node2.info.chooseIdentity())
node1.services.startFlow(initiatingFlow)
mockNet.runNetwork()
assertThat(receivedSessionMessages).startsWith(
node1 sent sessionInit(SendFlow::class, flowVersion = 1, payload = "Old initiating") to node2,
node2 sent sessionConfirm(flowVersion = 2) to node1
)
assertThat(initiatingFlow.getFlowInfo(node2.info.legalIdentity).flowVersion).isEqualTo(2)
assertThat(initiatingFlow.getFlowInfo(node2.info.chooseIdentity()).flowVersion).isEqualTo(2)
}
@Test
fun `unregistered flow`() {
val future = node1.services.startFlow(SendFlow("Hello", node2.info.legalIdentity)).resultFuture
val future = node1.services.startFlow(SendFlow("Hello", node2.info.chooseIdentity())).resultFuture
mockNet.runNetwork()
assertThatExceptionOfType(UnexpectedFlowEndException::class.java)
.isThrownBy { future.getOrThrow() }
@ -725,7 +718,7 @@ class FlowFrameworkTests {
@Test
fun `single inlined sub-flow`() {
node2.registerFlowFactory(SendAndReceiveFlow::class) { SingleInlinedSubFlow(it) }
val result = node1.services.startFlow(SendAndReceiveFlow(node2.info.legalIdentity, "Hello")).resultFuture
val result = node1.services.startFlow(SendAndReceiveFlow(node2.info.chooseIdentity(), "Hello")).resultFuture
mockNet.runNetwork()
assertThat(result.getOrThrow()).isEqualTo("HelloHello")
}
@ -733,7 +726,7 @@ class FlowFrameworkTests {
@Test
fun `double inlined sub-flow`() {
node2.registerFlowFactory(SendAndReceiveFlow::class) { DoubleInlinedSubFlow(it) }
val result = node1.services.startFlow(SendAndReceiveFlow(node2.info.legalIdentity, "Hello")).resultFuture
val result = node1.services.startFlow(SendAndReceiveFlow(node2.info.chooseIdentity(), "Hello")).resultFuture
mockNet.runNetwork()
assertThat(result.getOrThrow()).isEqualTo("HelloHello")
}
@ -788,7 +781,7 @@ class FlowFrameworkTests {
private fun StartedNode<*>.sendSessionMessage(message: SessionMessage, destination: StartedNode<*>) {
services.networkService.apply {
val address = getAddressOfParty(PartyInfo.Node(destination.info))
val address = getAddressOfParty(PartyInfo.SingleNode(destination.info.chooseIdentity(), emptyList()))
send(createMessage(StateMachineManager.sessionTopic, message.serialize().bytes), address)
}
}

View File

@ -15,6 +15,7 @@ import net.corda.core.utilities.seconds
import net.corda.node.internal.StartedNode
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.node.MockNetwork
@ -54,7 +55,7 @@ class NotaryServiceTests {
val inputState = issueState(clientNode)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
.setTimeWindow(Instant.now(), 30.seconds)
clientNode.services.signInitialTransaction(tx)
}
@ -70,7 +71,7 @@ class NotaryServiceTests {
val inputState = issueState(clientNode)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
clientNode.services.signInitialTransaction(tx)
}
@ -85,7 +86,7 @@ class NotaryServiceTests {
val inputState = issueState(clientNode)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
.setTimeWindow(Instant.now().plusSeconds(3600), 30.seconds)
clientNode.services.signInitialTransaction(tx)
}
@ -102,7 +103,7 @@ class NotaryServiceTests {
val inputState = issueState(clientNode)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
clientNode.services.signInitialTransaction(tx)
}
@ -122,14 +123,14 @@ class NotaryServiceTests {
val stx = run {
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
clientNode.services.signInitialTransaction(tx)
}
val stx2 = run {
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState)
.addInputState(issueState(clientNode))
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
clientNode.services.signInitialTransaction(tx)
}
@ -154,7 +155,7 @@ class NotaryServiceTests {
}
fun issueState(node: StartedNode<*>): StateAndRef<*> {
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.legalIdentity.ref(0))
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.chooseIdentity().ref(0))
val signedByNode = node.services.signInitialTransaction(tx)
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
node.services.recordTransactions(stx)

View File

@ -17,6 +17,7 @@ import net.corda.node.services.issueInvalidState
import net.corda.node.services.network.NetworkMapService
import net.corda.testing.DUMMY_NOTARY
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.node.MockNetwork
@ -56,7 +57,7 @@ class ValidatingNotaryServiceTests {
val inputState = issueInvalidState(clientNode, notaryNode.info.notaryIdentity)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
clientNode.services.signInitialTransaction(tx)
}
@ -97,7 +98,7 @@ class ValidatingNotaryServiceTests {
}
fun issueState(node: StartedNode<*>): StateAndRef<*> {
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.legalIdentity.ref(0))
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.chooseIdentity().ref(0))
val signedByNode = node.services.signInitialTransaction(tx)
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
node.services.recordTransactions(stx)

View File

@ -445,7 +445,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
val megaCorpServices = MockServices(MEGA_CORP_KEY)
database.transaction {
val freshKey = services.legalIdentityKey
val freshKey = services.myInfo.chooseIdentity().owningKey
// Issue a txn to Send us some Money
val usefulBuilder = TransactionBuilder(null).apply {
@ -477,11 +477,11 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `is ownable state relevant`() {
val service = (services.vaultService as NodeVaultService)
val amount = Amount(1000, Issued(BOC.ref(1), GBP))
val wellKnownCash = Cash.State(amount, services.myInfo.legalIdentity)
val wellKnownCash = Cash.State(amount, services.myInfo.chooseIdentity())
val myKeys = services.keyManagementService.filterMyKeys(listOf(wellKnownCash.owner.owningKey))
assertTrue { service.isRelevant(wellKnownCash, myKeys.toSet()) }
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(services.myInfo.legalIdentityAndCert, false)
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(services.myInfo.chooseIdentityAndCert(), false)
val anonymousCash = Cash.State(amount, anonymousIdentity.party)
val anonymousKeys = services.keyManagementService.filterMyKeys(listOf(anonymousCash.owner.owningKey))
assertTrue { service.isRelevant(anonymousCash, anonymousKeys.toSet()) }
@ -501,14 +501,14 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
service.updates.subscribe(this)
}
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(services.myInfo.legalIdentityAndCert, false)
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(services.myInfo.chooseIdentityAndCert(), false)
val thirdPartyIdentity = AnonymousParty(generateKeyPair().public)
val amount = Amount(1000, Issued(BOC.ref(1), GBP))
// Issue then move some cash
val issueTx = TransactionBuilder(services.myInfo.legalIdentity).apply {
val issueTx = TransactionBuilder(services.myInfo.chooseIdentity()).apply {
Cash().generateIssue(this,
amount, anonymousIdentity.party, services.myInfo.legalIdentity)
amount, anonymousIdentity.party, services.myInfo.chooseIdentity())
}.toWireTransaction()
val cashState = StateAndRef(issueTx.outputs.single(), StateRef(issueTx.id, 0))
@ -516,7 +516,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
val expectedIssueUpdate = Vault.Update(emptySet(), setOf(cashState), null)
database.transaction {
val moveTx = TransactionBuilder(services.myInfo.legalIdentity).apply {
val moveTx = TransactionBuilder(services.myInfo.chooseIdentity()).apply {
Cash.generateSpend(services, this, Amount(1000, GBP), thirdPartyIdentity)
}.toWireTransaction()
service.notify(moveTx)
@ -530,13 +530,13 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
@Test
fun `correct updates are generated when changing notaries`() {
val service = (services.vaultService as NodeVaultService)
val notary = services.myInfo.legalIdentity
val notary = services.myInfo.chooseIdentity()
val vaultSubscriber = TestSubscriber<Vault.Update<*>>().apply {
service.updates.subscribe(this)
}
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(services.myInfo.legalIdentityAndCert, false)
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(services.myInfo.chooseIdentityAndCert(), false)
val thirdPartyIdentity = AnonymousParty(generateKeyPair().public)
val amount = Amount(1000, Issued(BOC.ref(1), GBP))

View File

@ -235,7 +235,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
val dummyIssueBuilder = TransactionBuilder(notary = DUMMY_NOTARY).apply {
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)), DUMMY_LINEAR_CONTRACT_PROGRAM_ID)
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)), DUMMY_LINEAR_CONTRACT_PROGRAM_ID)
addCommand(dummyCommand(notaryServices.legalIdentityKey))
addCommand(dummyCommand(notaryServices.myInfo.chooseIdentity().owningKey))
}
val dummyIssue = notaryServices.signInitialTransaction(dummyIssueBuilder)
@ -255,7 +255,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
database.transaction { // Issue a linear state
val dummyIssueBuilder = TransactionBuilder(notary = DUMMY_NOTARY)
.addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)), DUMMY_LINEAR_CONTRACT_PROGRAM_ID)
.addCommand(dummyCommand(notaryServices.legalIdentityKey))
.addCommand(dummyCommand(notaryServices.myInfo.chooseIdentity().owningKey))
val dummyIssuePtx = notaryServices.signInitialTransaction(dummyIssueBuilder)
val dummyIssue = services.addSignature(dummyIssuePtx)
@ -271,7 +271,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
val dummyMoveBuilder = TransactionBuilder(notary = DUMMY_NOTARY)
.addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)), DUMMY_LINEAR_CONTRACT_PROGRAM_ID)
.addInputState(dummyIssue.tx.outRef<LinearState>(0))
.addCommand(dummyCommand(notaryServices.legalIdentityKey))
.addCommand(dummyCommand(notaryServices.myInfo.chooseIdentity().owningKey))
val dummyMove = notaryServices.signInitialTransaction(dummyMoveBuilder)
@ -347,7 +347,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
addOutputState(DummyDealContract.State(ref = "999", participants = listOf(freshIdentity)), DUMMY_DEAL_PROGRAM_ID)
addInputState(linearStates.first())
addInputState(deals.first())
addCommand(dummyCommand(notaryServices.legalIdentityKey))
addCommand(dummyCommand(notaryServices.myInfo.chooseIdentity().owningKey))
}
val dummyMove = notaryServices.signInitialTransaction(dummyMoveBuilder)

View File

@ -25,6 +25,7 @@ import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.getOrThrow
import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.driver.poll
import java.io.InputStream
import java.net.HttpURLConnection
@ -117,7 +118,7 @@ class AttachmentDemoFlow(val otherSide: Party, val notary: Party, val hash: Secu
// Create a trivial transaction with an output that describes the attachment, and the attachment itself
val ptx = TransactionBuilder(notary)
.addOutputState(AttachmentContract.State(hash), ATTACHMENT_PROGRAM_ID)
.addCommand(AttachmentContract.Command, serviceHub.legalIdentityKey)
.addCommand(AttachmentContract.Command, serviceHub.myInfo.chooseIdentity().owningKey)
.addAttachment(hash)
progressTracker.currentStep = SIGNING

Some files were not shown because too many files have changed in this diff Show More