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( sequence(
// TODO : Add test for remove when driver DSL support individual node shutdown. // TODO : Add test for remove when driver DSL support individual node shutdown.
expect { output: NetworkMapCache.MapChange -> 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 -> 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 -> 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`() { fun `cash issue and move`() {
val anonymous = false val anonymous = false
val (_, issueIdentity) = rpc.startFlow(::CashIssueFlow, 100.DOLLARS, OpaqueBytes.of(1), notaryNode.notaryIdentity).returnValue.getOrThrow() 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 issueSmId: StateMachineRunId? = null
var moveSmId: StateMachineRunId? = null var moveSmId: StateMachineRunId? = null
@ -167,7 +167,7 @@ class NodeMonitorModelTest : DriverBasedTest() {
// MOVE // MOVE
expect { add: StateMachineUpdate.Added -> expect { add: StateMachineUpdate.Added ->
val initiator = add.stateMachineInfo.initiator 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) require(stx.tx.outputs.size == 1)
val signaturePubKeys = stx.sigs.map { it.by }.toSet() val signaturePubKeys = stx.sigs.map { it.by }.toSet()
// Only Alice signed // Only Alice signed
val aliceKey = aliceNode.legalIdentity.owningKey val aliceKey = aliceNode.chooseIdentity().owningKey
require(signaturePubKeys.size <= aliceKey.keys.size) require(signaturePubKeys.size <= aliceKey.keys.size)
require(aliceKey.isFulfilledBy(signaturePubKeys)) require(aliceKey.isFulfilledBy(signaturePubKeys))
issueTx = stx issueTx = stx

View File

@ -38,7 +38,8 @@ class NetworkIdentityModel {
val parties: ObservableList<NodeInfo> = networkIdentities.filtered { !it.isCordaService() } val parties: ObservableList<NodeInfo> = networkIdentities.filtered { !it.isCordaService() }
val notaries: ObservableList<NodeInfo> = networkIdentities.filtered { it.advertisedServices.any { it.info.type.isNotary() } } 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 { private fun NodeInfo.isCordaService(): Boolean {
// TODO: better way to identify Corda service? // TODO: better way to identify Corda service?
@ -46,4 +47,11 @@ class NetworkIdentityModel {
} }
fun partyFromPublicKey(publicKey: PublicKey): ObservableValue<NodeInfo?> = identityCache[publicKey] 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.internal.StartedNode;
import net.corda.node.services.transactions.ValidatingNotaryService; import net.corda.node.services.transactions.ValidatingNotaryService;
import net.corda.nodeapi.User; import net.corda.nodeapi.User;
import net.corda.testing.CoreTestUtils;
import net.corda.testing.node.NodeBasedTest; import net.corda.testing.node.NodeBasedTest;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -74,7 +75,7 @@ public class CordaRPCJavaClientTest extends NodeBasedTest {
FlowHandle<AbstractCashFlow.Result> flowHandle = rpcProxy.startFlowDynamic(CashIssueFlow.class, FlowHandle<AbstractCashFlow.Result> flowHandle = rpcProxy.startFlowDynamic(CashIssueFlow.class,
DOLLARS(123), OpaqueBytes.of("1".getBytes()), DOLLARS(123), OpaqueBytes.of("1".getBytes()),
node.getInfo().getLegalIdentity()); CoreTestUtils.chooseIdentity(node.getInfo()));
System.out.println("Started issuing cash, waiting on result"); System.out.println("Started issuing cash, waiting on result");
flowHandle.getReturnValue().get(); 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.node.services.transactions.ValidatingNotaryService
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.ALICE import net.corda.testing.ALICE
import net.corda.testing.chooseIdentity
import net.corda.testing.node.NodeBasedTest import net.corda.testing.node.NodeBasedTest
import org.apache.activemq.artemis.api.core.ActiveMQSecurityException import org.apache.activemq.artemis.api.core.ActiveMQSecurityException
import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.assertj.core.api.Assertions.assertThatExceptionOfType
@ -81,7 +82,7 @@ class CordaRPCClientTest : NodeBasedTest() {
println("Creating proxy") println("Creating proxy")
println("Starting flow") println("Starting flow")
val flowHandle = connection!!.proxy.startTrackedFlow(::CashIssueFlow, 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") println("Started flow, waiting on result")
flowHandle.progress.subscribe { flowHandle.progress.subscribe {
@ -93,7 +94,7 @@ class CordaRPCClientTest : NodeBasedTest() {
@Test @Test
fun `sub-type of FlowException thrown by flow`() { fun `sub-type of FlowException thrown by flow`() {
login(rpcUser.username, rpcUser.password) 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 { assertThatExceptionOfType(CashException::class.java).isThrownBy {
handle.returnValue.getOrThrow() handle.returnValue.getOrThrow()
} }
@ -102,7 +103,7 @@ class CordaRPCClientTest : NodeBasedTest() {
@Test @Test
fun `check basic flow has no progress`() { fun `check basic flow has no progress`() {
login(rpcUser.username, rpcUser.password) 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<*>) assertFalse(it is FlowProgressHandle<*>)
assertTrue(it is FlowHandle<*>) assertTrue(it is FlowHandle<*>)
} }
@ -116,7 +117,7 @@ class CordaRPCClientTest : NodeBasedTest() {
assertTrue(startCash.isEmpty(), "Should not start with any cash") assertTrue(startCash.isEmpty(), "Should not start with any cash")
val flowHandle = proxy.startFlow(::CashIssueFlow, 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") println("Started issuing cash, waiting on result")
flowHandle.returnValue.get() flowHandle.returnValue.get()
@ -141,7 +142,7 @@ class CordaRPCClientTest : NodeBasedTest() {
countShellFlows++ 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() node.services.startFlow(CashIssueFlow(2000.DOLLARS, OpaqueBytes.of(0), nodeIdentity), FlowInitiator.Shell).resultFuture.getOrThrow()
proxy.startFlow(::CashIssueFlow, proxy.startFlow(::CashIssueFlow,
123.DOLLARS, 123.DOLLARS,

View File

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

View File

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

View File

@ -96,10 +96,10 @@ abstract class AbstractStateReplacementFlow {
@Suspendable @Suspendable
private fun collectSignatures(participants: Iterable<PublicKey>, stx: SignedTransaction): List<TransactionSignature> { 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 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") throw IllegalStateException("Participant $it to state $originalState not found on the network")
participantNode.legalIdentity
} }
val participantSignatures = parties.map { getParticipantSignature(it, stx) } val participantSignatures = parties.map { getParticipantSignature(it, stx) }
@ -193,7 +193,8 @@ abstract class AbstractStateReplacementFlow {
private fun checkMySignatureRequired(stx: SignedTransaction) { private fun checkMySignatureRequired(stx: SignedTransaction) {
// TODO: use keys from the keyManagementService instead // 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()) { val requiredKeys = if (stx.isNotaryChangeTransaction()) {
stx.resolveNotaryChangeTransaction(serviceHub).requiredSigningKeys stx.resolveNotaryChangeTransaction(serviceHub).requiredSigningKeys

View File

@ -20,7 +20,7 @@ class BroadcastTransactionFlow(val notarisedTransaction: SignedTransaction,
@Suspendable @Suspendable
override fun call() { override fun call() {
// TODO: Messaging layer should handle this broadcast for us // 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. // SendTransactionFlow allows otherParty to access our data to resolve the transaction.
subFlow(SendTransactionFlow(participant, notarisedTransaction)) subFlow(SendTransactionFlow(participant, notarisedTransaction))
} }

View File

@ -77,7 +77,7 @@ class CollectSignaturesFlow @JvmOverloads constructor (val partiallySignedTx: Si
@Suspendable override fun call(): SignedTransaction { @Suspendable override fun call(): SignedTransaction {
// Check the signatures which have already been provided and that the transaction is valid. // 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. // 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 signed = partiallySignedTx.sigs.map { it.by }
val notSigned = partiallySignedTx.tx.requiredSigningKeys - signed 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 * @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). * 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) fun tracker() = ProgressTracker(NOTARISING, BROADCASTING)
} }
open protected val ourIdentity: Party get() = serviceHub.myInfo.legalIdentity
@Suspendable @Suspendable
@Throws(NotaryException::class) @Throws(NotaryException::class)
override fun call(): List<SignedTransaction> { 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. // Each transaction has its own set of recipients, but extra recipients get them all.
progressTracker.currentStep = BROADCASTING progressTracker.currentStep = BROADCASTING
for ((stx, parties) in notarisedTxns) { 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()) { if (participants.isNotEmpty()) {
broadcastTransaction(stx, participants.toNonEmptySet()) broadcastTransaction(stx, participants.toNonEmptySet())
} }

View File

@ -3,6 +3,7 @@ package net.corda.core.flows
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.FlowStateMachine import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.abbreviate import net.corda.core.internal.abbreviate
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed
@ -56,6 +57,12 @@ abstract class FlowLogic<out T> {
@Suspendable @Suspendable
fun initiateFlow(party: Party): FlowSession = stateMachine.initiateFlow(party, flowUsedForSessions) 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 * 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. * 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() 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) // Filter participants down to the set of those not in the network map (are not well known)
val confidentialIdentities = identities val confidentialIdentities = identities
.filter { serviceHub.networkMapCache.getNodeByLegalIdentityKey(it.owningKey) == null } .filter { serviceHub.networkMapCache.getNodesByLegalIdentityKey(it.owningKey).isEmpty() }
.toList() .toList()
val identityCertificates: Map<AbstractParty, PartyAndCertificate?> = identities val identityCertificates: Map<AbstractParty, PartyAndCertificate?> = identities
.map { Pair(it, serviceHub.identityService.certificateFromKey(it.owningKey)) }.toMap() .map { Pair(it, serviceHub.identityService.certificateFromKey(it.owningKey)) }.toMap()

View File

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

View File

@ -5,6 +5,7 @@ import net.corda.core.concurrent.CordaFuture
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.flows.* import net.corda.core.flows.*
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.UntrustworthyData import net.corda.core.utilities.UntrustworthyData
@ -49,4 +50,5 @@ interface FlowStateMachine<R> {
val id: StateMachineRunId val id: StateMachineRunId
val resultFuture: CordaFuture<R> val resultFuture: CordaFuture<R>
val flowInitiator: FlowInitiator 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 * Returns the RPC protocol version, which is the same the node's Platform Version. Exists since version 1 so guaranteed
* to be present. * 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. * 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> 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 * 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. * 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. // 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 @CordaSerializable
data class NodeInfo(val addresses: List<NetworkHostAndPort>, data class NodeInfo(val addresses: List<NetworkHostAndPort>,
// TODO After removing of services these two fields will be merged together and made NonEmptySet. val legalIdentitiesAndCerts: List<PartyAndCertificate>,
val legalIdentityAndCert: PartyAndCertificate,
val legalIdentitiesAndCerts: Set<PartyAndCertificate>,
val platformVersion: Int, val platformVersion: Int,
val advertisedServices: List<ServiceEntry> = emptyList(), val advertisedServices: List<ServiceEntry> = emptyList(),
val serial: Long val serial: Long
) { ) {
init { init {
require(advertisedServices.none { it.identity == legalIdentityAndCert }) { require(legalIdentitiesAndCerts.isNotEmpty()) { "Node should have at least one legal identity" }
"Service identities must be different from node 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 val notaryIdentity: Party get() = advertisedServices.single { it.info.type.isNotary() }.identity.party
fun serviceIdentities(type: ServiceType): List<Party> { fun serviceIdentities(type: ServiceType): List<Party> {
return advertisedServices.mapNotNull { if (it.info.type.isSubTypeOf(type)) it.identity.party else null } 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. * Uses node's owner X500 name to infer the node's location. Used in Explorer in map view.
*/ */
fun getWorldMapLocation(): WorldMapLocation? { fun getWorldMapLocation(): WorldMapLocation? {
val nodeOwnerLocation = legalIdentity.name.locality val nodeOwnerLocation = legalIdentitiesAndCerts.first().name.locality
return nodeOwnerLocation.let { CityDatabase[it] } 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.SignableData
import net.corda.core.crypto.SignatureMetadata import net.corda.core.crypto.SignatureMetadata
import net.corda.core.crypto.TransactionSignature 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.node.services.*
import net.corda.core.serialization.SerializeAsToken import net.corda.core.serialization.SerializeAsToken
import net.corda.core.transactions.FilteredTransaction import net.corda.core.transactions.FilteredTransaction
@ -129,16 +131,7 @@ interface ServiceHub : ServicesForResolution {
} }
} }
/** private val legalIdentityKey: PublicKey get() = this.myInfo.legalIdentitiesAndCerts.first().owningKey
* 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
/** /**
* Helper property to shorten code for fetching the the [PublicKey] portion of the * Helper property to shorten code for fetching the the [PublicKey] portion of the
@ -288,4 +281,4 @@ interface ServiceHub : ServicesForResolution {
* @return A new [Connection] * @return A new [Connection]
*/ */
fun jdbcSession(): 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.internal.randomOrNull
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.node.ServiceEntry
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
import rx.Observable import rx.Observable
@ -58,6 +59,14 @@ interface NetworkMapCache {
return partyNodes.filter { it.advertisedServices.any { it.info.type.isSubTypeOf(serviceType) } } 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. * 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, * 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. */ /** Look up the node info for a host and port. */
fun getNodeByAddress(address: NetworkHostAndPort): NodeInfo? 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 * 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 services it provides. In case of a distributed service run by multiple nodes each participant advertises
* the identity of the *whole group*. * the identity of the *whole group*.
*/ */
/** Look up the node infos for a specific peer key. */
/** Look up the node info for a specific peer key. */ fun getNodesByLegalIdentityKey(identityKey: PublicKey): List<NodeInfo>
fun getNodeByLegalIdentityKey(identityKey: PublicKey): NodeInfo?
/** Look up all nodes advertising the service owned by [publicKey] */ /** Look up all nodes advertising the service owned by [publicKey] */
fun getNodesByAdvertisedServiceIdentityKey(publicKey: PublicKey): List<NodeInfo> { fun getNodesByAdvertisedServiceIdentityKey(publicKey: PublicKey): List<NodeInfo> {

View File

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

View File

@ -34,7 +34,7 @@ object NodeInfoSchemaV1 : MappedSchema(
@JoinTable(name = "link_nodeinfo_party", @JoinTable(name = "link_nodeinfo_party",
joinColumns = arrayOf(JoinColumn(name="node_info_id")), joinColumns = arrayOf(JoinColumn(name="node_info_id")),
inverseJoinColumns = arrayOf(JoinColumn(name="party_name"))) inverseJoinColumns = arrayOf(JoinColumn(name="party_name")))
val legalIdentitiesAndCerts: Set<DBPartyAndCertificate>, val legalIdentitiesAndCerts: List<DBPartyAndCertificate>,
@Column(name = "platform_version") @Column(name = "platform_version")
val platformVersion: Int, val platformVersion: Int,
@ -54,8 +54,7 @@ object NodeInfoSchemaV1 : MappedSchema(
fun toNodeInfo(): NodeInfo { fun toNodeInfo(): NodeInfo {
return NodeInfo( return NodeInfo(
this.addresses.map { it.toHostAndPort() }, 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 } + this.legalIdentitiesAndCerts.filter { !it.isMain }).map { it.toLegalIdentityAndCert() },
this.legalIdentitiesAndCerts.filter { !it.isMain }.map { it.toLegalIdentityAndCert() }.toSet(),
this.platformVersion, this.platformVersion,
this.advertisedServices.map { this.advertisedServices.map {
it.serviceEntry?.deserialize<ServiceEntry>() ?: throw IllegalStateException("Service entry shouldn't be null") 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 com.google.common.primitives.Primitives;
import net.corda.core.identity.Party; import net.corda.core.identity.Party;
import net.corda.node.internal.StartedNode; import net.corda.node.internal.StartedNode;
import net.corda.testing.CoreTestUtils;
import net.corda.testing.node.MockNetwork; import net.corda.testing.node.MockNetwork;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -39,7 +40,7 @@ public class FlowsInJavaTest {
@Test @Test
public void suspendableActionInsideUnwrap() throws Exception { public void suspendableActionInsideUnwrap() throws Exception {
node2.getInternals().registerInitiatedFlow(SendHelloAndThenReceive.class); 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(); mockNet.runNetwork();
assertThat(result.get()).isEqualTo("Hello"); assertThat(result.get()).isEqualTo("Hello");
} }
@ -54,7 +55,7 @@ public class FlowsInJavaTest {
} }
private void primitiveReceiveTypeTest(Class<?> receiveType) throws InterruptedException { 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(); Future<?> result = node1.getServices().startFlow(flow).getResultFuture();
mockNet.runNetwork(); mockNet.runNetwork();
try { try {

View File

@ -7,6 +7,7 @@ import net.corda.core.transactions.TransactionBuilder
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.TestDependencyInjectionBase import net.corda.testing.TestDependencyInjectionBase
import net.corda.testing.contracts.DUMMY_PROGRAM_ID import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand import net.corda.testing.dummyCommand
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
@ -68,8 +69,8 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
tx.addInputState(makeDummyStateAndRef(i.toString())) tx.addInputState(makeDummyStateAndRef(i.toString()))
tx.addOutputState(makeDummyState(i), DUMMY_PROGRAM_ID) tx.addOutputState(makeDummyState(i), DUMMY_PROGRAM_ID)
tx.addOutputState(makeDummyState(i.toString()), DUMMY_PROGRAM_ID) tx.addOutputState(makeDummyState(i.toString()), DUMMY_PROGRAM_ID)
tx.addCommand(Commands.Cmd1(i), listOf(services.myInfo.legalIdentity.owningKey)) tx.addCommand(Commands.Cmd1(i), listOf(services.myInfo.chooseIdentity().owningKey))
tx.addCommand(Commands.Cmd2(i), listOf(services.myInfo.legalIdentity.owningKey)) tx.addCommand(Commands.Cmd2(i), listOf(services.myInfo.chooseIdentity().owningKey))
} }
return tx.toLedgerTransaction(services) 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.persistence.NodeAttachmentService
import net.corda.node.services.transactions.SimpleNotaryService import net.corda.node.services.transactions.SimpleNotaryService
import net.corda.node.utilities.DatabaseTransactionManager import net.corda.node.utilities.DatabaseTransactionManager
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@ -72,7 +73,7 @@ class AttachmentTests {
// Get node one to run a flow to fetch it and insert it. // Get node one to run a flow to fetch it and insert it.
mockNet.runNetwork() mockNet.runNetwork()
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.legalIdentity) val f1 = n1.startAttachmentFlow(setOf(id), n0.info.chooseIdentity())
mockNet.runNetwork() mockNet.runNetwork()
assertEquals(0, f1.resultFuture.getOrThrow().fromDisk.size) 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. // Shut down node zero and ensure node one can still resolve the attachment.
n0.dispose() 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]) assertEquals(attachment, response.fromDisk[0])
} }
@ -106,7 +107,7 @@ class AttachmentTests {
// Get node one to fetch a non-existent attachment. // Get node one to fetch a non-existent attachment.
val hash = SecureHash.randomSHA256() val hash = SecureHash.randomSHA256()
mockNet.runNetwork() mockNet.runNetwork()
val f1 = n1.startAttachmentFlow(setOf(hash), n0.info.legalIdentity) val f1 = n1.startAttachmentFlow(setOf(hash), n0.info.chooseIdentity())
mockNet.runNetwork() mockNet.runNetwork()
val e = assertFailsWith<FetchDataFlow.HashNotFound> { f1.resultFuture.getOrThrow() } val e = assertFailsWith<FetchDataFlow.HashNotFound> { f1.resultFuture.getOrThrow() }
assertEquals(hash, e.requested) assertEquals(hash, e.requested)
@ -151,7 +152,7 @@ class AttachmentTests {
// Get n1 to fetch the attachment. Should receive corrupted bytes. // Get n1 to fetch the attachment. Should receive corrupted bytes.
mockNet.runNetwork() mockNet.runNetwork()
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.legalIdentity) val f1 = n1.startAttachmentFlow(setOf(id), n0.info.chooseIdentity())
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith<FetchDataFlow.DownloadedVsRequestedDataMismatch> { f1.resultFuture.getOrThrow() } 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.MINI_CORP_KEY
import net.corda.testing.contracts.DUMMY_PROGRAM_ID import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.contracts.DummyContract 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.MockNetwork
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import org.junit.After 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. // 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. // "collectSignaturesFlow" and "SignTransactionFlow" can be used in practise.
object TestFlow { object TestFlow {
@InitiatingFlow @InitiatingFlow
@ -89,7 +91,7 @@ class CollectSignaturesFlowTests {
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
val myInputKeys = state.participants.map { it.owningKey } 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 command = Command(DummyContract.Commands.Create(), myInputKeys)
val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), command) val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), command)
val ptx = serviceHub.signInitialTransaction(builder) val ptx = serviceHub.signInitialTransaction(builder)
@ -145,7 +147,7 @@ class CollectSignaturesFlowTests {
@Test @Test
fun `successfully collects two signatures`() { fun `successfully collects two signatures`() {
val bConfidentialIdentity = b.database.transaction { val bConfidentialIdentity = b.database.transaction {
b.services.keyManagementService.freshKeyAndCert(b.info.legalIdentityAndCert, false) b.services.keyManagementService.freshKeyAndCert(b.info.chooseIdentityAndCert(), false)
} }
a.database.transaction { a.database.transaction {
// Normally this is handled by TransactionKeyFlow, but here we have to manually let A know about the identity // 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) registerFlowOnAllNodes(TestFlowTwo.Responder::class)
val magicNumber = 1337 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 state = DummyContract.MultiOwnerState(magicNumber, parties)
val flow = a.services.startFlow(TestFlowTwo.Initiator(state)) val flow = a.services.startFlow(TestFlowTwo.Initiator(state))
mockNet.runNetwork() mockNet.runNetwork()
@ -165,7 +167,7 @@ class CollectSignaturesFlowTests {
@Test @Test
fun `no need to collect any signatures`() { 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 ptx = a.services.signInitialTransaction(onePartyDummyContract)
val flow = a.services.startFlow(CollectSignaturesFlow(ptx)) val flow = a.services.startFlow(CollectSignaturesFlow(ptx))
mockNet.runNetwork() mockNet.runNetwork()
@ -177,7 +179,7 @@ class CollectSignaturesFlowTests {
@Test @Test
fun `fails when not signed by initiator`() { 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 miniCorpServices = MockServices(MINI_CORP_KEY)
val ptx = miniCorpServices.signInitialTransaction(onePartyDummyContract) val ptx = miniCorpServices.signInitialTransaction(onePartyDummyContract)
val flow = a.services.startFlow(CollectSignaturesFlow(ptx)) val flow = a.services.startFlow(CollectSignaturesFlow(ptx))
@ -190,9 +192,9 @@ class CollectSignaturesFlowTests {
@Test @Test
fun `passes with multiple initial signatures`() { fun `passes with multiple initial signatures`() {
val twoPartyDummyContract = DummyContract.generateInitial(1337, notary, val twoPartyDummyContract = DummyContract.generateInitial(1337, notary,
a.info.legalIdentity.ref(1), a.info.chooseIdentity().ref(1),
b.info.legalIdentity.ref(2), b.info.chooseIdentity().ref(2),
b.info.legalIdentity.ref(3)) b.info.chooseIdentity().ref(3))
val signedByA = a.services.signInitialTransaction(twoPartyDummyContract) val signedByA = a.services.signInitialTransaction(twoPartyDummyContract)
val signedByBoth = b.services.addSignature(signedByA) val signedByBoth = b.services.addSignature(signedByA)
val flow = a.services.startFlow(CollectSignaturesFlow(signedByBoth)) val flow = a.services.startFlow(CollectSignaturesFlow(signedByBoth))
@ -202,4 +204,3 @@ class CollectSignaturesFlowTests {
println(result.sigs) 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.node.services.FlowPermissions.Companion.startFlowPermission
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.RPCDriverExposedDSLInterface import net.corda.testing.RPCDriverExposedDSLInterface
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.contracts.DummyContractV2 import net.corda.testing.contracts.DummyContractV2
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
@ -73,11 +74,11 @@ class ContractUpgradeFlowTest {
@Test @Test
fun `2 parties contract upgrade`() { fun `2 parties contract upgrade`() {
// Create dummy contract. // 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 signedByA = a.services.signInitialTransaction(twoPartyDummyContract)
val stx = b.services.addSignature(signedByA) 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() mockNet.runNetwork()
val atx = a.database.transaction { a.services.validatedTransactions.getTransaction(stx.id) } val atx = a.database.transaction { a.services.validatedTransactions.getTransaction(stx.id) }
@ -143,7 +144,7 @@ class ContractUpgradeFlowTest {
fun `2 parties contract upgrade using RPC`() { fun `2 parties contract upgrade using RPC`() {
rpcDriver(initialiseSerialization = false) { rpcDriver(initialiseSerialization = false) {
// Create dummy contract. // 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 signedByA = a.services.signInitialTransaction(twoPartyDummyContract)
val stx = b.services.addSignature(signedByA) val stx = b.services.addSignature(signedByA)
@ -156,7 +157,7 @@ class ContractUpgradeFlowTest {
)) ))
val rpcA = startProxy(a, user) val rpcA = startProxy(a, user)
val rpcB = startProxy(b, 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() mockNet.runNetwork()
handle.returnValue.getOrThrow() handle.returnValue.getOrThrow()
@ -218,6 +219,7 @@ class ContractUpgradeFlowTest {
@Test @Test
fun `upgrade Cash to v2`() { fun `upgrade Cash to v2`() {
// Create some cash. // Create some cash.
val chosenIdentity = a.info.chooseIdentity()
val result = a.services.startFlow(CashIssueFlow(Amount(1000, USD), OpaqueBytes.of(1), notary)).resultFuture val result = a.services.startFlow(CashIssueFlow(Amount(1000, USD), OpaqueBytes.of(1), notary)).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
val stx = result.getOrThrow().stx val stx = result.getOrThrow().stx
@ -232,7 +234,7 @@ class ContractUpgradeFlowTest {
// Get contract state from the vault. // Get contract state from the vault.
val firstState = a.database.transaction { a.services.vaultQueryService.queryBy<ContractState>().states.single() } 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.") 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.") 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.finance.contracts.asset.Cash
import net.corda.testing.ALICE import net.corda.testing.ALICE
import net.corda.node.internal.StartedNode import net.corda.node.internal.StartedNode
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import org.junit.After import org.junit.After
@ -42,9 +43,9 @@ class FinalityFlowTests {
@Test @Test
fun `finalise a simple transaction`() { 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) 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 stx = nodeA.services.signInitialTransaction(builder)
val flow = nodeA.services.startFlow(FinalityFlow(stx)) val flow = nodeA.services.startFlow(FinalityFlow(stx))
mockNet.runNetwork() mockNet.runNetwork()
@ -59,7 +60,7 @@ class FinalityFlowTests {
@Test @Test
fun `reject a transaction with unknown parties`() { 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 fakeIdentity = ALICE // Alice isn't part of this network, so node A won't recognise them
val builder = TransactionBuilder(notary) val builder = TransactionBuilder(notary)
Cash().generateIssue(builder, amount, fakeIdentity, 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.ALICE
import net.corda.testing.BOB import net.corda.testing.BOB
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@ -39,8 +40,8 @@ class IdentitySyncFlowTests {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name) val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val alice: Party = aliceNode.services.myInfo.legalIdentity val alice: Party = aliceNode.services.myInfo.chooseIdentity()
val bob: Party = bobNode.services.myInfo.legalIdentity val bob: Party = bobNode.services.myInfo.chooseIdentity()
bobNode.internals.registerInitiatedFlow(Receive::class.java) bobNode.internals.registerInitiatedFlow(Receive::class.java)
// Alice issues then pays some cash to a new confidential identity that Bob doesn't know about // 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.GBP
import net.corda.finance.contracts.asset.Cash import net.corda.finance.contracts.asset.Cash
import net.corda.node.internal.StartedNode import net.corda.node.internal.StartedNode
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import org.junit.After import org.junit.After
@ -43,11 +44,11 @@ class ManualFinalityFlowTests {
@Test @Test
fun `finalise a simple transaction`() { 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) 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 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() mockNet.runNetwork()
val result = flow.resultFuture.getOrThrow() val result = flow.resultFuture.getOrThrow()
val notarisedTx = result.single() 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.ALICE
import net.corda.testing.BOB import net.corda.testing.BOB
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -24,8 +25,9 @@ class SwapIdentitiesFlowTests {
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name) val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name) val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val alice: Party = aliceNode.services.myInfo.legalIdentity val alice: Party = aliceNode.services.myInfo.chooseIdentity()
val bob: Party = bobNode.services.myInfo.legalIdentity val bob: Party = bobNode.services.myInfo.chooseIdentity()
mockNet.registerIdentities()
// Run the flows // Run the flows
val requesterFlow = aliceNode.services.startFlow(SwapIdentitiesFlow(bob)) 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
import net.corda.testing.MEGA_CORP_KEY import net.corda.testing.MEGA_CORP_KEY
import net.corda.testing.MINI_CORP import net.corda.testing.MINI_CORP
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
@ -59,7 +60,7 @@ class ResolveTransactionsFlowTest {
@Test @Test
fun `resolve from two hashes`() { fun `resolve from two hashes`() {
val (stx1, stx2) = makeTransactions() 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 val future = b.services.startFlow(p).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
val results = future.getOrThrow() val results = future.getOrThrow()
@ -74,7 +75,7 @@ class ResolveTransactionsFlowTest {
@Test @Test
fun `dependency with an error`() { fun `dependency with an error`() {
val stx = makeTransactions(signFirstTX = false).second 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 val future = b.services.startFlow(p).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith(SignedTransaction.SignaturesMissingException::class) { future.getOrThrow() } assertFailsWith(SignedTransaction.SignaturesMissingException::class) { future.getOrThrow() }
@ -83,7 +84,7 @@ class ResolveTransactionsFlowTest {
@Test @Test
fun `resolve from a signed transaction`() { fun `resolve from a signed transaction`() {
val (stx1, stx2) = makeTransactions() 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 val future = b.services.startFlow(p).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() future.getOrThrow()
@ -108,7 +109,7 @@ class ResolveTransactionsFlowTest {
} }
cursor = stx 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 val future = b.services.startFlow(p).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
assertFailsWith<ResolveTransactionsFlow.ExcessivelyLargeTransactionGraph> { future.getOrThrow() } assertFailsWith<ResolveTransactionsFlow.ExcessivelyLargeTransactionGraph> { future.getOrThrow() }
@ -132,7 +133,7 @@ class ResolveTransactionsFlowTest {
a.services.recordTransactions(stx2, stx3) 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 val future = b.services.startFlow(p).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() future.getOrThrow()
@ -154,7 +155,7 @@ class ResolveTransactionsFlowTest {
a.services.attachments.importAttachment(makeJar()) a.services.attachments.importAttachment(makeJar())
} }
val stx2 = makeTransactions(withAttachment = id).second 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 val future = b.services.startFlow(p).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
future.getOrThrow() 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.network.NetworkMapService
import net.corda.node.services.persistence.NodeAttachmentService import net.corda.node.services.persistence.NodeAttachmentService
import net.corda.node.utilities.DatabaseTransactionManager import net.corda.node.utilities.DatabaseTransactionManager
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@ -96,7 +97,7 @@ class AttachmentSerializationTest {
@InitiatingFlow @InitiatingFlow
private abstract class ClientLogic(server: StartedNode<*>) : FlowLogic<ClientResult>() { private abstract class ClientLogic(server: StartedNode<*>) : FlowLogic<ClientResult>() {
internal val server = server.info.legalIdentity internal val server = server.info.chooseIdentity()
@Suspendable @Suspendable
internal fun communicate() { 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.toSignedTransaction`` to sign a ``TransactionBuilder`` and convert it into a ``SignedTransaction``
* ``ServiceHub.createSignature`` and ``ServiceHub.addSignature`` to create and add signatures to 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 Finally, ``ServiceHub`` exposes notary identity key via ``ServiceHub.notaryIdentityKey``.
identity key (via ``ServiceHub.notaryIdentityKey``).

View File

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

View File

@ -134,15 +134,14 @@ public class FlowCookbookJava {
// We may also need to identify a specific counterparty. // We may also need to identify a specific counterparty.
// Again, we do so using the network map. // Again, we do so using the network map.
// DOCSTART 2 // DOCSTART 2
Party namedCounterparty = getServiceHub().getNetworkMapCache().getNodeByLegalName(new CordaX500Name("NodeA", "London", "UK")).getLegalIdentity(); Party namedCounterparty = getServiceHub().getIdentityService().partyFromX500Name(new CordaX500Name("NodeA", "London", "UK"));
Party keyedCounterparty = getServiceHub().getNetworkMapCache().getNodeByLegalIdentityKey(dummyPubKey).getLegalIdentity(); Party keyedCounterparty = getServiceHub().getIdentityService().partyFromKey(dummyPubKey);
Party firstCounterparty = getServiceHub().getNetworkMapCache().getPartyNodes().get(0).getLegalIdentity();
// DOCEND 2 // DOCEND 2
// Finally, we can use the map to identify nodes providing a // Finally, we can use the map to identify nodes providing a
// specific service (e.g. a regulator or an oracle). // specific service (e.g. a regulator or an oracle).
// DOCSTART 3 // 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 // DOCEND 3
/*------------------------------ /*------------------------------
@ -267,7 +266,7 @@ public class FlowCookbookJava {
// matching every public key in all of the transaction's commands. // matching every public key in all of the transaction's commands.
// DOCSTART 24 // DOCSTART 24
DummyContract.Commands.Create commandData = new DummyContract.Commands.Create(); DummyContract.Commands.Create commandData = new DummyContract.Commands.Create();
PublicKey ourPubKey = getServiceHub().getLegalIdentityKey(); PublicKey ourPubKey = getServiceHub().getMyInfo().getLegalIdentitiesAndCerts().get(0).getOwningKey();
PublicKey counterpartyPubKey = counterparty.getOwningKey(); PublicKey counterpartyPubKey = counterparty.getOwningKey();
List<PublicKey> requiredSigners = ImmutableList.of(ourPubKey, counterpartyPubKey); List<PublicKey> requiredSigners = ImmutableList.of(ourPubKey, counterpartyPubKey);
Command<DummyContract.Commands.Create> ourCommand = new Command<>(commandData, requiredSigners); 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 issueRef = OpaqueBytes.of(0)
val parties = proxy.networkMapSnapshot() val parties = proxy.networkMapSnapshot()
val notary = parties.first { it.advertisedServices.any { it.info.type.isNotary() } }.notaryIdentity 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) { while (true) {
Thread.sleep(1000) Thread.sleep(1000)
val random = SplittableRandom() 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.CashException
import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashIssueFlow
import net.corda.finance.flows.CashPaymentFlow import net.corda.finance.flows.CashPaymentFlow
import net.corda.testing.chooseIdentity
import java.util.* import java.util.*
// DOCSTART CustomVaultQuery // DOCSTART CustomVaultQuery
@ -139,7 +140,7 @@ object TopupIssuerFlow {
val issueTx = subFlow(issueCashFlow) val issueTx = subFlow(issueCashFlow)
// NOTE: issueCashFlow performs a Broadcast (which stores a local copy of the txn to the ledger) // NOTE: issueCashFlow performs a Broadcast (which stores a local copy of the txn to the ledger)
// short-circuit when issuing to self // short-circuit when issuing to self
if (issueTo == serviceHub.myInfo.legalIdentity) if (issueTo == serviceHub.myInfo.chooseIdentity())
return issueTx return issueTx
// now invoke Cash subflow to Move issued assetType to issue requester // now invoke Cash subflow to Move issued assetType to issue requester
progressTracker.currentStep = TRANSFERRING progressTracker.currentStep = TRANSFERRING

View File

@ -112,18 +112,17 @@ object FlowCookbook {
val firstNotary: Party = serviceHub.networkMapCache.notaryNodes[0].notaryIdentity val firstNotary: Party = serviceHub.networkMapCache.notaryNodes[0].notaryIdentity
// DOCEND 1 // DOCEND 1
// We may also need to identify a specific counterparty. Again, we // We may also need to identify a specific counterparty. We
// do so using the network map. // do so using identity service.
// DOCSTART 2 // DOCSTART 2
val namedCounterparty: Party? = serviceHub.networkMapCache.getNodeByLegalName(CordaX500Name(organisation = "NodeA", locality = "London", country = "UK"))?.legalIdentity val namedCounterparty: Party? = serviceHub.identityService.partyFromX500Name(CordaX500Name(organisation = "NodeA", locality = "London", country = "UK"))
val keyedCounterparty: Party? = serviceHub.networkMapCache.getNodeByLegalIdentityKey(dummyPubKey)?.legalIdentity val keyedCounterparty: Party? = serviceHub.identityService.partyFromKey(dummyPubKey)
val firstCounterparty: Party = serviceHub.networkMapCache.partyNodes[0].legalIdentity
// DOCEND 2 // DOCEND 2
// Finally, we can use the map to identify nodes providing a // Finally, we can use the map to identify nodes providing a
// specific service (e.g. a regulator or an oracle). // specific service (e.g. a regulator or an oracle).
// DOCSTART 3 // 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 // DOCEND 3
/**----------------------------- /**-----------------------------
@ -248,7 +247,7 @@ object FlowCookbook {
// matching every public key in all of the transaction's commands. // matching every public key in all of the transaction's commands.
// DOCSTART 24 // DOCSTART 24
val commandData: DummyContract.Commands.Create = DummyContract.Commands.Create() 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 counterpartyPubKey: PublicKey = counterparty.owningKey
val requiredSigners: List<PublicKey> = listOf(ourPubKey, counterpartyPubKey) val requiredSigners: List<PublicKey> = listOf(ourPubKey, counterpartyPubKey)
val ourCommand: Command<DummyContract.Commands.Create> = Command(commandData, requiredSigners) 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_PROGRAM_ID
import net.corda.finance.contracts.asset.Cash import net.corda.finance.contracts.asset.Cash
import net.corda.finance.schemas.CashSchemaV1 import net.corda.finance.schemas.CashSchemaV1
import net.corda.testing.chooseIdentity
import java.util.* import java.util.*
@CordaSerializable @CordaSerializable
@ -74,7 +75,7 @@ private fun prepareOurInputsAndOutputs(serviceHub: ServiceHub, lockId: UUID, req
val outputs = if (residual > 0L) { val outputs = if (residual > 0L) {
// Build an output state for the residual change back to us // Build an output state for the residual change back to us
val residualAmount = Amount(residual, sellAmount.token) 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) listOf(transferedFundsOutput, residualOutput)
} else { } else {
listOf(transferedFundsOutput) listOf(transferedFundsOutput)
@ -96,11 +97,11 @@ class ForeignExchangeFlow(val tradeId: String,
// Select correct sides of the Fx exchange to query for. // Select correct sides of the Fx exchange to query for.
// Specifically we own the assets we wish to sell. // Specifically we own the assets we wish to sell.
// Also prepare the other side query // 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 local = FxRequest(tradeId, baseCurrencyAmount, baseCurrencySeller, baseCurrencyBuyer)
val remote = FxRequest(tradeId, quoteCurrencyAmount, baseCurrencyBuyer, baseCurrencySeller) val remote = FxRequest(tradeId, quoteCurrencyAmount, baseCurrencyBuyer, baseCurrencySeller)
Pair(local, remote) Pair(local, remote)
} else if (baseCurrencyBuyer == serviceHub.myInfo.legalIdentity) { } else if (baseCurrencyBuyer == serviceHub.myInfo.chooseIdentity()) {
val local = FxRequest(tradeId, quoteCurrencyAmount, baseCurrencyBuyer, baseCurrencySeller) val local = FxRequest(tradeId, quoteCurrencyAmount, baseCurrencyBuyer, baseCurrencySeller)
val remote = FxRequest(tradeId, baseCurrencyAmount, baseCurrencySeller, baseCurrencyBuyer) val remote = FxRequest(tradeId, baseCurrencyAmount, baseCurrencySeller, baseCurrencyBuyer)
Pair(local, remote) Pair(local, remote)
@ -132,7 +133,7 @@ class ForeignExchangeFlow(val tradeId: String,
>= remoteRequestWithNotary.amount.quantity) { >= remoteRequestWithNotary.amount.quantity) {
"the provided inputs don't provide sufficient funds" "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) { map { it.amount.quantity }.sum() == remoteRequestWithNotary.amount.quantity) {
"the provided outputs don't provide the request 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 // the lifecycle of the Fx trades which would be included in the transaction
// Check request is for us // Check request is for us
require(serviceHub.myInfo.legalIdentity == it.owner) { require(serviceHub.myInfo.chooseIdentity() == it.owner) {
"Request does not include the correct counterparty" "Request does not include the correct counterparty"
} }
require(source == it.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.transactions.TransactionBuilder
import net.corda.core.utilities.seconds import net.corda.core.utilities.seconds
import net.corda.core.utilities.unwrap import net.corda.core.utilities.unwrap
import net.corda.testing.chooseIdentity
// Minimal state model of a manual approval process // Minimal state model of a manual approval process
@CordaSerializable @CordaSerializable
@ -102,7 +103,7 @@ class SubmitTradeApprovalFlow(val tradeId: String,
// Manufacture an initial state // Manufacture an initial state
val tradeProposal = TradeApprovalContract.State( val tradeProposal = TradeApprovalContract.State(
tradeId, tradeId,
serviceHub.myInfo.legalIdentity, serviceHub.myInfo.chooseIdentity(),
counterparty) counterparty)
// identify a notary. This might also be done external to the flow // identify a notary. This might also be done external to the flow
val notary = serviceHub.networkMapCache.getAnyNotary() val notary = serviceHub.networkMapCache.getAnyNotary()
@ -113,7 +114,7 @@ class SubmitTradeApprovalFlow(val tradeId: String,
// We can automatically sign as there is no untrusted data. // We can automatically sign as there is no untrusted data.
val signedTx = serviceHub.signInitialTransaction(tx) val signedTx = serviceHub.signInitialTransaction(tx)
// Notarise and distribute. // Notarise and distribute.
subFlow(FinalityFlow(signedTx, setOf(serviceHub.myInfo.legalIdentity, counterparty))) subFlow(FinalityFlow(signedTx, setOf(serviceHub.myInfo.chooseIdentity(), counterparty)))
// Return the initial state // Return the initial state
return signedTx.tx.outRef<TradeApprovalContract.State>(0) 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}" "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. // 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" "The counterparty must give the verdict"
} }
@ -170,7 +171,7 @@ class SubmitCompletionFlow(val ref: StateRef, val verdict: WorkflowState) : Flow
latestRecord, latestRecord,
StateAndContract(newState, TRADE_APPROVAL_PROGRAM_ID), StateAndContract(newState, TRADE_APPROVAL_PROGRAM_ID),
Command(TradeApprovalContract.Commands.Completed(), 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) tx.setTimeWindow(serviceHub.clock.instant(), 60.seconds)
// We can sign this transaction immediately as we have already checked all the fields and the decision // 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. // 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 // First we receive the verdict transaction signed by their single key
val completeTx = receive<SignedTransaction>(source).unwrap { val completeTx = receive<SignedTransaction>(source).unwrap {
// Check the transaction is signed apart from our own key and the notary // 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 // Check the transaction data is correctly formed
val ltx = it.toLedgerTransaction(serviceHub, false) val ltx = it.toLedgerTransaction(serviceHub, false)
ltx.verify() ltx.verify()
@ -224,7 +225,7 @@ class RecordCompletionFlow(val source: Party) : FlowLogic<Unit>() {
// Check the context dependent parts of the transaction as the // Check the context dependent parts of the transaction as the
// Contract verify method must not use serviceHub queries. // Contract verify method must not use serviceHub queries.
val state = ltx.outRef<TradeApprovalContract.State>(0) 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" "Proposal not one of our original proposals"
} }
require(state.state.data.counterparty == source) { 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.node.services.transactions.ValidatingNotaryService
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.DUMMY_NOTARY_KEY import net.corda.testing.DUMMY_NOTARY_KEY
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.After import org.junit.After
import org.junit.Assert import org.junit.Assert
@ -77,9 +78,9 @@ class CustomVaultQueryTest {
private fun topUpCurrencies() { private fun topUpCurrencies() {
val flowHandle1 = nodeA.services.startFlow(TopupIssuerFlow.TopupIssuanceRequester( val flowHandle1 = nodeA.services.startFlow(TopupIssuerFlow.TopupIssuanceRequester(
nodeA.info.legalIdentity, nodeA.info.chooseIdentity(),
OpaqueBytes.of(0x01), OpaqueBytes.of(0x01),
nodeA.info.legalIdentity, nodeA.info.chooseIdentity(),
notaryNode.info.notaryIdentity)) notaryNode.info.notaryIdentity))
flowHandle1.resultFuture.getOrThrow() 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.node.services.transactions.ValidatingNotaryService
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.DUMMY_NOTARY_KEY import net.corda.testing.DUMMY_NOTARY_KEY
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@ -69,10 +70,10 @@ class FxTransactionBuildTutorialTest {
// Now run the actual Fx exchange // Now run the actual Fx exchange
val doIt = nodeA.services.startFlow(ForeignExchangeFlow("trade1", val doIt = nodeA.services.startFlow(ForeignExchangeFlow("trade1",
POUNDS(100).issuedBy(nodeB.info.legalIdentity.ref(0x01)), POUNDS(100).issuedBy(nodeB.info.chooseIdentity().ref(0x01)),
DOLLARS(200).issuedBy(nodeA.info.legalIdentity.ref(0x01)), DOLLARS(200).issuedBy(nodeA.info.chooseIdentity().ref(0x01)),
nodeA.info.legalIdentity, nodeA.info.chooseIdentity(),
nodeB.info.legalIdentity)) nodeB.info.chooseIdentity()))
// wait for the flow to finish and the vault updates to be done // wait for the flow to finish and the vault updates to be done
doIt.resultFuture.getOrThrow() doIt.resultFuture.getOrThrow()
// Get the balances when the vault updates // 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.node.services.transactions.ValidatingNotaryService
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.DUMMY_NOTARY_KEY import net.corda.testing.DUMMY_NOTARY_KEY
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@ -55,7 +56,7 @@ class WorkflowTransactionBuildTutorialTest {
// Setup a vault subscriber to wait for successful upload of the proposal to NodeB // Setup a vault subscriber to wait for successful upload of the proposal to NodeB
val nodeBVaultUpdate = nodeB.services.vaultService.updates.toFuture() val nodeBVaultUpdate = nodeB.services.vaultService.updates.toFuture()
// Kick of the proposal flow // 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 // Wait for the flow to finish
val proposalRef = flow1.resultFuture.getOrThrow() val proposalRef = flow1.resultFuture.getOrThrow()
val proposalLinearId = proposalRef.state.data.linearId val proposalLinearId = proposalRef.state.data.linearId
@ -71,8 +72,8 @@ class WorkflowTransactionBuildTutorialTest {
// Confirm the state as as expected // Confirm the state as as expected
assertEquals(WorkflowState.NEW, proposalRef.state.data.state) assertEquals(WorkflowState.NEW, proposalRef.state.data.state)
assertEquals("1234", proposalRef.state.data.tradeId) assertEquals("1234", proposalRef.state.data.tradeId)
assertEquals(nodeA.info.legalIdentity, proposalRef.state.data.source) assertEquals(nodeA.info.chooseIdentity(), proposalRef.state.data.source)
assertEquals(nodeB.info.legalIdentity, proposalRef.state.data.counterparty) assertEquals(nodeB.info.chooseIdentity(), proposalRef.state.data.counterparty)
assertEquals(proposalRef, latestFromA) assertEquals(proposalRef, latestFromA)
assertEquals(proposalRef, latestFromB) assertEquals(proposalRef, latestFromB)
// Setup a vault subscriber to pause until the final update is in NodeA and NodeB // 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 // Confirm the state is as expected
assertEquals(WorkflowState.APPROVED, completedRef.state.data.state) assertEquals(WorkflowState.APPROVED, completedRef.state.data.state)
assertEquals("1234", completedRef.state.data.tradeId) assertEquals("1234", completedRef.state.data.tradeId)
assertEquals(nodeA.info.legalIdentity, completedRef.state.data.source) assertEquals(nodeA.info.chooseIdentity(), completedRef.state.data.source)
assertEquals(nodeB.info.legalIdentity, completedRef.state.data.counterparty) assertEquals(nodeB.info.chooseIdentity(), completedRef.state.data.counterparty)
assertEquals(completedRef, finalFromA) assertEquals(completedRef, finalFromA)
assertEquals(completedRef, finalFromB) assertEquals(completedRef, finalFromB)
} }

View File

@ -59,8 +59,6 @@ with the following:
/** The flow logic is encapsulated within the call() method. */ /** The flow logic is encapsulated within the call() method. */
@Suspendable @Suspendable
override fun call() { override fun call() {
// We retrieve the required identities from the network map.
val me = serviceHub.myInfo.legalIdentity
val notary = serviceHub.networkMapCache.getAnyNotary() val notary = serviceHub.networkMapCache.getAnyNotary()
// We create a transaction builder // We create a transaction builder
@ -124,7 +122,6 @@ with the following:
@Override @Override
public Void call() throws FlowException { public Void call() throws FlowException {
// We retrieve the required identities from the network map. // We retrieve the required identities from the network map.
final Party me = getServiceHub().getMyInfo().getLegalIdentity();
final Party notary = getServiceHub().getNetworkMapCache().getAnyNotary(null); final Party notary = getServiceHub().getNetworkMapCache().getAnyNotary(null);
// We create a transaction builder. // 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 .. sourcecode:: kotlin
val myIdentity = serviceHub.myInfo.legalIdentity val myIdentity = serviceHub.chooseIdentity()
val state = DummyContract.SingleOwnerState(magicNumber = 42, owner = myIdentity.owningKey) 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 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 .. sourcecode:: kotlin
val mySigningKey: PublicKey = serviceHub.legalIdentityKey val mySigningKey: PublicKey = serviceHub.chooseIdentity().owningKey
val issueTransaction = serviceHub.toSignedTransaction(issueTransaction, mySigningKey) val issueTransaction = serviceHub.toSignedTransaction(issueTransaction, mySigningKey)
serviceHub.recordTransactions(issueTransaction) serviceHub.recordTransactions(issueTransaction)

View File

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

View File

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

View File

@ -54,7 +54,7 @@ object TwoPartyDealFlow {
@Suspendable override fun call(): SignedTransaction { @Suspendable override fun call(): SignedTransaction {
progressTracker.currentStep = GENERATING_ID progressTracker.currentStep = GENERATING_ID
val txIdentities = subFlow(SwapIdentitiesFlow(otherParty)) 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() val anonymousCounterparty = txIdentities.get(otherParty) ?: otherParty.anonymise()
progressTracker.currentStep = SENDING_PROPOSAL progressTracker.currentStep = SENDING_PROPOSAL
// Make the first message we'll send to kick off the flow. // 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 ... " } logger.trace { "Got signatures from other party, verifying ... " }
progressTracker.currentStep = RECORDING 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." } logger.trace { "Recorded transaction." }
@ -150,7 +150,7 @@ object TwoPartyDealFlow {
val wellKnownOtherParty = serviceHub.identityService.partyFromAnonymous(it.primaryIdentity) val wellKnownOtherParty = serviceHub.identityService.partyFromAnonymous(it.primaryIdentity)
val wellKnownMe = serviceHub.identityService.partyFromAnonymous(it.secondaryIdentity) val wellKnownMe = serviceHub.identityService.partyFromAnonymous(it.secondaryIdentity)
require(wellKnownOtherParty == otherParty) require(wellKnownOtherParty == otherParty)
require(wellKnownMe == serviceHub.myInfo.legalIdentity) require(wellKnownMe == ourIdentity.party)
validateHandshake(it) 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! // 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. // But it can't hurt to have one.
ptx.setTimeWindow(serviceHub.clock.instant(), 30.seconds) 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 notaryNode: NodeInfo,
val assetToSell: StateAndRef<OwnableState>, val assetToSell: StateAndRef<OwnableState>,
val price: Amount<Currency>, 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>() { override val progressTracker: ProgressTracker = Seller.tracker()) : FlowLogic<SignedTransaction>() {
companion object { companion object {
@ -82,7 +82,7 @@ object TwoPartyTradeFlow {
override fun call(): SignedTransaction { override fun call(): SignedTransaction {
progressTracker.currentStep = AWAITING_PROPOSAL progressTracker.currentStep = AWAITING_PROPOSAL
// Make the first message we'll send to kick off the flow. // 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, // 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! // but we must check it out thoroughly before we sign!
// SendTransactionFlow allows otherParty to access our data to resolve the transaction. // 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") 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 // Create the identity we'll be paying to, and send the counterparty proof we own the identity
val buyerAnonymousIdentity = if (anonymous) val buyerAnonymousIdentity = if (anonymous)
serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.legalIdentityAndCert, false) serviceHub.keyManagementService.freshKeyAndCert(ourIdentity, false)
else else
serviceHub.myInfo.legalIdentityAndCert ourIdentity
// Put together a proposed transaction that performs the trade, and sign it. // Put together a proposed transaction that performs the trade, and sign it.
progressTracker.currentStep = SIGNING progressTracker.currentStep = SIGNING
val (ptx, cashSigningPubKeys) = assembleSharedTX(assetForSale, tradeRequest, buyerAnonymousIdentity) 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. // 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 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) val issueBuilder = CommercialPaper().generateIssue(issuance, faceValue, TEST_TX_TIME + 30.days, DUMMY_NOTARY)
issueBuilder.setTimeWindow(TEST_TX_TIME, 30.seconds) issueBuilder.setTimeWindow(TEST_TX_TIME, 30.seconds)
val issuePtx = bigCorpServices.signInitialTransaction(issueBuilder) 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.`issued by`
import net.corda.finance.contracts.asset.Cash import net.corda.finance.contracts.asset.Cash
import net.corda.node.internal.StartedNode import net.corda.node.internal.StartedNode
import net.corda.testing.chooseIdentity
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetwork.MockNode import net.corda.testing.node.MockNetwork.MockNode
@ -31,7 +32,7 @@ class CashExitFlowTests {
notaryNode = nodes.notaryNode notaryNode = nodes.notaryNode
bankOfCordaNode = nodes.partyNodes[0] bankOfCordaNode = nodes.partyNodes[0]
notary = notaryNode.info.notaryIdentity notary = notaryNode.info.notaryIdentity
bankOfCorda = bankOfCordaNode.info.legalIdentity bankOfCorda = bankOfCordaNode.info.chooseIdentity()
mockNet.runNetwork() mockNet.runNetwork()
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture 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.`issued by`
import net.corda.finance.contracts.asset.Cash import net.corda.finance.contracts.asset.Cash
import net.corda.node.internal.StartedNode import net.corda.node.internal.StartedNode
import net.corda.testing.chooseIdentity
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetwork.MockNode import net.corda.testing.node.MockNetwork.MockNode
@ -29,7 +30,7 @@ class CashIssueFlowTests {
notaryNode = nodes.notaryNode notaryNode = nodes.notaryNode
bankOfCordaNode = nodes.partyNodes[0] bankOfCordaNode = nodes.partyNodes[0]
notary = notaryNode.info.notaryIdentity notary = notaryNode.info.notaryIdentity
bankOfCorda = bankOfCordaNode.info.legalIdentity bankOfCorda = bankOfCordaNode.info.chooseIdentity()
mockNet.runNetwork() mockNet.runNetwork()
} }

View File

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

View File

@ -1,11 +1,11 @@
package net.corda.nodeapi package net.corda.nodeapi
import net.corda.core.identity.CordaX500Name
import net.corda.core.utilities.toBase58String import net.corda.core.utilities.toBase58String
import net.corda.core.identity.Party
import net.corda.core.messaging.MessageRecipientGroup import net.corda.core.messaging.MessageRecipientGroup
import net.corda.core.messaging.MessageRecipients import net.corda.core.messaging.MessageRecipients
import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.node.NodeInfo
import net.corda.core.node.services.ServiceType
import net.corda.core.internal.read import net.corda.core.internal.read
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.SingletonSerializeAsToken
@ -29,8 +29,7 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
const val PEER_USER = "SystemUsers/Peer" const val PEER_USER = "SystemUsers/Peer"
const val INTERNAL_PREFIX = "internal." const val INTERNAL_PREFIX = "internal."
const val PEERS_PREFIX = "${INTERNAL_PREFIX}peers." const val PEERS_PREFIX = "${INTERNAL_PREFIX}peers." //TODO Come up with better name for common peers/services queue
const val SERVICES_PREFIX = "${INTERNAL_PREFIX}services."
const val IP_REQUEST_PREFIX = "ip." const val IP_REQUEST_PREFIX = "ip."
const val P2P_QUEUE = "p2p.inbound" const val P2P_QUEUE = "p2p.inbound"
const val NOTIFICATIONS_ADDRESS = "${INTERNAL_PREFIX}activemq.notifications" const val NOTIFICATIONS_ADDRESS = "${INTERNAL_PREFIX}activemq.notifications"
@ -64,13 +63,9 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
@CordaSerializable @CordaSerializable
data class NodeAddress(override val queueName: String, override val hostAndPort: NetworkHostAndPort) : ArtemisPeerAddress { data class NodeAddress(override val queueName: String, override val hostAndPort: NetworkHostAndPort) : ArtemisPeerAddress {
companion object { companion object {
fun asPeer(peerIdentity: PublicKey, hostAndPort: NetworkHostAndPort): NodeAddress { fun asSingleNode(peerIdentity: PublicKey, hostAndPort: NetworkHostAndPort): NodeAddress {
return NodeAddress("$PEERS_PREFIX${peerIdentity.toBase58String()}", hostAndPort) 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. * @param identity The service identity's owning key.
*/ */
data class ServiceAddress(val identity: PublicKey) : ArtemisAddress, MessageRecipientGroup { 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 */ /** 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 { // Used for bridges creation.
return if (nodeInfo.advertisedServices.any { it.info.type == ServiceType.networkMap }) { fun getArtemisPeerAddress(party: Party, address: NetworkHostAndPort, netMapName: CordaX500Name? = null): ArtemisPeerAddress {
NetworkMapAddress(nodeInfo.addresses.first()) return if (party.name == netMapName) {
NetworkMapAddress(address)
} else { } 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 { sealed class ConnectionDirection {
data class Inbound(val acceptorFactoryClassName: String) : ConnectionDirection() data class Inbound(val acceptorFactoryClassName: String) : ConnectionDirection()
data class Outbound( 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 val connectorFactoryClassName: String = NettyConnectorFactory::class.java.name
) : ConnectionDirection() ) : ConnectionDirection()
} }
@ -67,7 +67,7 @@ class ArtemisTcpTransport {
TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME to CIPHER_SUITES.joinToString(","), TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME to CIPHER_SUITES.joinToString(","),
TransportConstants.ENABLED_PROTOCOLS_PROP_NAME to "TLSv1.2", TransportConstants.ENABLED_PROTOCOLS_PROP_NAME to "TLSv1.2",
TransportConstants.NEED_CLIENT_AUTH_PROP_NAME to true, 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) options.putAll(tlsOptions)
} }

View File

@ -14,6 +14,7 @@ import net.corda.testing.BOB
import net.corda.core.utilities.unwrap import net.corda.core.utilities.unwrap
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.chooseIdentity
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.Test import org.junit.Test
@ -30,7 +31,7 @@ class CordappScanningDriverTest {
val initiatedFlowClass = alice.rpcClientToNode() val initiatedFlowClass = alice.rpcClientToNode()
.start(user.username, user.password) .start(user.username, user.password)
.proxy .proxy
.startFlow(::ReceiveFlow, bob.nodeInfo.legalIdentity) .startFlow(::ReceiveFlow, bob.nodeInfo.chooseIdentity())
.returnValue .returnValue
assertThat(initiatedFlowClass.getOrThrow()).isEqualTo(SendSubClassFlow::class.java.name) 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.FlowPermissions.Companion.startFlowPermission
import net.corda.node.services.transactions.SimpleNotaryService import net.corda.node.services.transactions.SimpleNotaryService
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.chooseIdentity
import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.performance.div import net.corda.testing.performance.div
@ -116,7 +117,7 @@ class NodePerformanceTests {
doneFutures.transpose().get() doneFutures.transpose().get()
println("STARTING PAYMENT") println("STARTING PAYMENT")
startPublishingFixedRateInjector(metricRegistry, 8, 5.minutes, 100L / TimeUnit.SECONDS) { 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`() { fun `service is accessible through getAnyServiceOfType`() {
driver(startNodesInProcess = true) { driver(startNodesInProcess = true) {
val bankA = startNode(rpcUsers = listOf(User(user, pass, setOf(startFlowPermission<ServiceTypeCheckingFlow>())))).get() 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 -> bankA.rpcClientToNode().use(user, pass) { connection ->
val result = connection.proxy.startFlow(::ServiceTypeCheckingFlow).returnValue.get() val result = connection.proxy.startFlow(::ServiceTypeCheckingFlow).returnValue.get()
assertTrue(result) 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.minClusterSize
import net.corda.node.services.transactions.minCorrectReplicas import net.corda.node.services.transactions.minCorrectReplicas
import net.corda.node.utilities.ServiceIdentityGenerator import net.corda.node.utilities.ServiceIdentityGenerator
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DUMMY_PROGRAM_ID import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand import net.corda.testing.dummyCommand
@ -53,11 +54,12 @@ class BFTNotaryServiceTests {
replicaIds.map { mockNet.baseDirectory(mockNet.nextNodeId + it) }, replicaIds.map { mockNet.baseDirectory(mockNet.nextNodeId + it) },
serviceType.id, serviceType.id,
clusterName) clusterName)
val bftNotaryService = ServiceInfo(serviceType, clusterName) val bftNotaryService = ServiceInfo(serviceType)
val notaryClusterAddresses = replicaIds.map { NetworkHostAndPort("localhost", 11000 + it * 10) } val notaryClusterAddresses = replicaIds.map { NetworkHostAndPort("localhost", 11000 + it * 10) }
replicaIds.forEach { replicaId -> replicaIds.forEach { replicaId ->
mockNet.createNode( mockNet.createNode(
node.network.myAddress, node.network.myAddress,
legalName = clusterName.copy(organisation = clusterName.organisation + replicaId),
advertisedServices = bftNotaryService, advertisedServices = bftNotaryService,
configOverrides = { configOverrides = {
whenever(it.bftSMaRt).thenReturn(BFTSMaRtConfiguration(replicaId, false, exposeRaces)) 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 notary = bftNotaryCluster(minClusterSize(1), true) // This true adds a sleep to expose the race.
val f = node.run { val f = node.run {
val trivialTx = signInitialTransaction(notary) { 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: // Create a new consensus while the redundant replica is sleeping:
services.startFlow(NotaryFlow.Client(trivialTx)).resultFuture services.startFlow(NotaryFlow.Client(trivialTx)).resultFuture
@ -97,7 +99,7 @@ class BFTNotaryServiceTests {
val notary = bftNotaryCluster(clusterSize) val notary = bftNotaryCluster(clusterSize)
node.run { node.run {
val issueTx = signInitialTransaction(notary) { val issueTx = signInitialTransaction(notary) {
addOutputState(DummyContract.SingleOwnerState(owner = info.legalIdentity), DUMMY_PROGRAM_ID) addOutputState(DummyContract.SingleOwnerState(owner = (info.chooseIdentity())), DUMMY_PROGRAM_ID)
} }
database.transaction { database.transaction {
services.recordTransactions(issueTx) services.recordTransactions(issueTx)
@ -132,7 +134,7 @@ class BFTNotaryServiceTests {
assertEquals(StateRef(issueTx.id, 0), stateRef) assertEquals(StateRef(issueTx.id, 0), stateRef)
assertEquals(spendTxs[successfulIndex].id, consumingTx.id) assertEquals(spendTxs[successfulIndex].id, consumingTx.id)
assertEquals(0, consumingTx.inputIndex) assertEquals(0, consumingTx.inputIndex)
assertEquals(info.legalIdentity, consumingTx.requestingParty) assertEquals(info.chooseIdentity(), consumingTx.requestingParty)
} }
} }
} }
@ -145,7 +147,7 @@ private fun StartedNode<*>.signInitialTransaction(
): SignedTransaction { ): SignedTransaction {
return services.signInitialTransaction( return services.signInitialTransaction(
TransactionBuilder(notary).apply { TransactionBuilder(notary).apply {
addCommand(dummyCommand(services.legalIdentityKey)) addCommand(dummyCommand(services.myInfo.chooseIdentity().owningKey))
block() block()
}) })
} }

View File

@ -2,11 +2,11 @@ package net.corda.node.services
import net.corda.core.contracts.Amount import net.corda.core.contracts.Amount
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.StateMachineUpdate import net.corda.core.messaging.StateMachineUpdate
import net.corda.core.messaging.startFlow import net.corda.core.messaging.startFlow
import net.corda.core.node.NodeInfo
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.finance.POUNDS import net.corda.finance.POUNDS
@ -29,7 +29,7 @@ class DistributedServiceTests : DriverBasedTest() {
lateinit var notaries: List<NodeHandle.OutOfProcess> lateinit var notaries: List<NodeHandle.OutOfProcess>
lateinit var aliceProxy: CordaRPCOps lateinit var aliceProxy: CordaRPCOps
lateinit var raftNotaryIdentity: Party lateinit var raftNotaryIdentity: Party
lateinit var notaryStateMachines: Observable<Pair<NodeInfo, StateMachineUpdate>> lateinit var notaryStateMachines: Observable<Pair<Party, StateMachineUpdate>>
override fun setup() = driver { override fun setup() = driver {
// Start Alice and 3 notaries in a RAFT cluster // Start Alice and 3 notaries in a RAFT cluster
@ -51,8 +51,13 @@ class DistributedServiceTests : DriverBasedTest() {
raftNotaryIdentity = notaryIdentity raftNotaryIdentity = notaryIdentity
notaries = notaryNodes.map { it as NodeHandle.OutOfProcess } 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, 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 // Connect to Alice and the notaries
fun connectRpc(node: NodeHandle): CordaRPCOps { fun connectRpc(node: NodeHandle): CordaRPCOps {
@ -62,7 +67,7 @@ class DistributedServiceTests : DriverBasedTest() {
aliceProxy = connectRpc(alice) aliceProxy = connectRpc(alice)
val rpcClientsToNotaries = notaries.map(::connectRpc) val rpcClientsToNotaries = notaries.map(::connectRpc)
notaryStateMachines = Observable.from(rpcClientsToNotaries.map { proxy -> 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() }).flatMap { it.onErrorResumeNext(Observable.empty()) }.bufferUntilSubscribed()
runTest() runTest()
@ -82,10 +87,10 @@ class DistributedServiceTests : DriverBasedTest() {
// The state machines added in the notaries should map one-to-one to notarisation requests // The state machines added in the notaries should map one-to-one to notarisation requests
val notarisationsPerNotary = HashMap<Party, Int>() val notarisationsPerNotary = HashMap<Party, Int>()
notaryStateMachines.expectEvents(isStrict = false) { notaryStateMachines.expectEvents(isStrict = false) {
replicate<Pair<NodeInfo, StateMachineUpdate>>(50) { replicate<Pair<Party, StateMachineUpdate>>(50) {
expect(match = { it.second is StateMachineUpdate.Added }) { (notary, update) -> expect(match = { it.second is StateMachineUpdate.Added }) { (notary, update) ->
update as StateMachineUpdate.Added 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>() val notarisationsPerNotary = HashMap<Party, Int>()
notaryStateMachines.expectEvents(isStrict = false) { notaryStateMachines.expectEvents(isStrict = false) {
replicate<Pair<NodeInfo, StateMachineUpdate>>(30) { replicate<Pair<Party, StateMachineUpdate>>(30) {
expect(match = { it.second is StateMachineUpdate.Added }) { (notary, update) -> expect(match = { it.second is StateMachineUpdate.Added }) { (notary, update) ->
update as StateMachineUpdate.Added 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>) { 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.DUMMY_PROGRAM_ID
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand import net.corda.testing.dummyCommand
import net.corda.testing.chooseIdentity
import net.corda.testing.node.NodeBasedTest import net.corda.testing.node.NodeBasedTest
import org.junit.Ignore
import org.junit.Test import org.junit.Test
import java.util.* import java.util.*
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -25,6 +27,7 @@ import kotlin.test.assertFailsWith
class RaftNotaryServiceTests : NodeBasedTest() { class RaftNotaryServiceTests : NodeBasedTest() {
private val notaryName = CordaX500Name(organisation = "RAFT Notary Service", locality = "London", country = "GB") private val notaryName = CordaX500Name(organisation = "RAFT Notary Service", locality = "London", country = "GB")
@Ignore
@Test @Test
fun `detect double spend`() { fun `detect double spend`() {
val (bankA) = listOf( val (bankA) = listOf(
@ -38,16 +41,16 @@ class RaftNotaryServiceTests : NodeBasedTest() {
val firstTxBuilder = TransactionBuilder(notaryParty) val firstTxBuilder = TransactionBuilder(notaryParty)
.addInputState(inputState) .addInputState(inputState)
.addCommand(dummyCommand(bankA.services.legalIdentityKey)) .addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey))
val firstSpendTx = bankA.services.signInitialTransaction(firstTxBuilder) val firstSpendTx = bankA.services.signInitialTransaction(firstTxBuilder)
val firstSpend = bankA.services.startFlow(NotaryFlow.Client(firstSpendTx)) val firstSpend = bankA.services.startFlow(NotaryFlow.Client(firstSpendTx))
firstSpend.resultFuture.getOrThrow() firstSpend.resultFuture.getOrThrow()
val secondSpendBuilder = TransactionBuilder(notaryParty).withItems(inputState).run { 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) addOutputState(dummyState, DUMMY_PROGRAM_ID)
addCommand(dummyCommand(bankA.services.legalIdentityKey)) addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey))
this this
} }
val secondSpendTx = bankA.services.signInitialTransaction(secondSpendBuilder) val secondSpendTx = bankA.services.signInitialTransaction(secondSpendBuilder)
@ -60,7 +63,7 @@ class RaftNotaryServiceTests : NodeBasedTest() {
private fun issueState(node: StartedNode<*>, notary: Party): StateAndRef<*> { private fun issueState(node: StartedNode<*>, notary: Party): StateAndRef<*> {
return node.database.transaction { 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) val stx = node.services.signInitialTransaction(builder)
node.services.recordTransactions(stx) node.services.recordTransactions(stx)
StateAndRef(builder.outputStates().first(), StateRef(stx.id, 0)) 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.core.utilities.unwrap
import net.corda.testing.ALICE import net.corda.testing.ALICE
import net.corda.testing.BOB import net.corda.testing.BOB
import net.corda.testing.chooseIdentity
import net.corda.testing.node.NodeBasedTest import net.corda.testing.node.NodeBasedTest
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.Test import org.junit.Test
@ -21,7 +22,7 @@ class FlowVersioningTest : NodeBasedTest() {
startNode(BOB.name, platformVersion = 3)).transpose().getOrThrow() startNode(BOB.name, platformVersion = 3)).transpose().getOrThrow()
bob.internals.installCoreFlow(PretendInitiatingCoreFlow::class, ::PretendInitiatedCoreFlow) bob.internals.installCoreFlow(PretendInitiatingCoreFlow::class, ::PretendInitiatedCoreFlow)
val (alicePlatformVersionAccordingToBob, bobPlatformVersionAccordingToAlice) = alice.services.startFlow( val (alicePlatformVersionAccordingToBob, bobPlatformVersionAccordingToAlice) = alice.services.startFlow(
PretendInitiatingCoreFlow(bob.info.legalIdentity)).resultFuture.getOrThrow() PretendInitiatingCoreFlow(bob.info.chooseIdentity())).resultFuture.getOrThrow()
assertThat(alicePlatformVersionAccordingToBob).isEqualTo(2) assertThat(alicePlatformVersionAccordingToBob).isEqualTo(2)
assertThat(bobPlatformVersionAccordingToAlice).isEqualTo(3) 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.DUMMY_NOTARY
import net.corda.testing.aliceBobAndNotary import net.corda.testing.aliceBobAndNotary
import net.corda.testing.contracts.DUMMY_PROGRAM_ID import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyState import net.corda.testing.contracts.DummyState
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.dummyCommand import net.corda.testing.dummyCommand
@ -28,14 +29,14 @@ class LargeTransactionsTest {
override fun call() { override fun call() {
val tx = TransactionBuilder(notary = DUMMY_NOTARY) val tx = TransactionBuilder(notary = DUMMY_NOTARY)
.addOutputState(DummyState(), DUMMY_PROGRAM_ID) .addOutputState(DummyState(), DUMMY_PROGRAM_ID)
.addCommand(dummyCommand(serviceHub.legalIdentityKey)) .addCommand(dummyCommand(serviceHub.myInfo.chooseIdentity().owningKey))
.addAttachment(hash1) .addAttachment(hash1)
.addAttachment(hash2) .addAttachment(hash2)
.addAttachment(hash3) .addAttachment(hash3)
.addAttachment(hash4) .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. // 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)) subFlow(SendTransactionFlow(bob, stx))
receive<Unit>(bob) 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.RPCApi
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.nodeapi.config.SSLConfiguration import net.corda.nodeapi.config.SSLConfiguration
import net.corda.testing.chooseIdentity
import net.corda.testing.configureTestSSL import net.corda.testing.configureTestSSL
import net.corda.testing.messaging.SimpleMQClient import net.corda.testing.messaging.SimpleMQClient
import net.corda.testing.node.NodeBasedTest import net.corda.testing.node.NodeBasedTest
@ -86,7 +87,7 @@ abstract class MQSecurityTest : NodeBasedTest() {
@Test @Test
fun `create queue for peer which has not been communicated with`() { fun `create queue for peer which has not been communicated with`() {
val bob = startNode(BOB.name).getOrThrow() val bob = startNode(BOB.name).getOrThrow()
assertAllQueueCreationAttacksFail("$PEERS_PREFIX${bob.info.legalIdentity.owningKey.toBase58String()}") assertAllQueueCreationAttacksFail("$PEERS_PREFIX${bob.info.chooseIdentity().owningKey.toBase58String()}")
} }
@Test @Test
@ -219,7 +220,7 @@ abstract class MQSecurityTest : NodeBasedTest() {
private fun startBobAndCommunicateWithAlice(): Party { private fun startBobAndCommunicateWithAlice(): Party {
val bob = startNode(BOB.name).getOrThrow() val bob = startNode(BOB.name).getOrThrow()
bob.internals.registerInitiatedFlow(ReceiveFlow::class.java) 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 // Perform a protocol exchange to force the peer queue to be created
alice.services.startFlow(SendFlow(bobParty, 0)).resultFuture.getOrThrow() alice.services.startFlow(SendFlow(bobParty, 0)).resultFuture.getOrThrow()
return bobParty return bobParty

View File

@ -22,6 +22,7 @@ import net.corda.node.utilities.ServiceIdentityGenerator
import net.corda.testing.* import net.corda.testing.*
import net.corda.testing.node.NodeBasedTest import net.corda.testing.node.NodeBasedTest
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.Ignore
import org.junit.Test import org.junit.Test
import java.util.* import java.util.*
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
@ -68,25 +69,25 @@ class P2PMessagingTest : NodeBasedTest() {
RaftValidatingNotaryService.type.id, RaftValidatingNotaryService.type.id,
DISTRIBUTED_SERVICE_NAME) DISTRIBUTED_SERVICE_NAME)
val distributedService = ServiceInfo(RaftValidatingNotaryService.type, DISTRIBUTED_SERVICE_NAME)
val notaryClusterAddress = freeLocalHostAndPort() val notaryClusterAddress = freeLocalHostAndPort()
startNetworkMapNode( startNetworkMapNode(
DUMMY_MAP.name, DUMMY_MAP.name,
advertisedServices = setOf(distributedService), advertisedServices = setOf(ServiceInfo(RaftValidatingNotaryService.type, DUMMY_MAP.name.copy(commonName = "DistributedService"))),
configOverrides = mapOf("notaryNodeAddress" to notaryClusterAddress.toString())) configOverrides = mapOf("notaryNodeAddress" to notaryClusterAddress.toString()))
val (serviceNode2, alice) = listOf( val (serviceNode2, alice) = listOf(
startNode( startNode(
SERVICE_2_NAME, SERVICE_2_NAME,
advertisedServices = setOf(distributedService), advertisedServices = setOf(ServiceInfo(RaftValidatingNotaryService.type, SERVICE_2_NAME.copy(commonName = "DistributedService"))),
configOverrides = mapOf( configOverrides = mapOf(
"notaryNodeAddress" to freeLocalHostAndPort().toString(), "notaryNodeAddress" to freeLocalHostAndPort().toString(),
"notaryClusterAddresses" to listOf(notaryClusterAddress.toString()))), "notaryClusterAddresses" to listOf(notaryClusterAddress.toString()))),
startNode(ALICE.name) startNode(ALICE.name)
).transpose().getOrThrow() ).transpose().getOrThrow()
assertAllNodesAreUsed(listOf(networkMapNode, serviceNode2), DISTRIBUTED_SERVICE_NAME, alice) assertAllNodesAreUsed(listOf(networkMapNode, serviceNode2), SERVICE_2_NAME.copy(commonName = "DistributedService"), alice)
} }
@Ignore
@Test @Test
fun `communicating with a distributed service which we're part of`() { fun `communicating with a distributed service which we're part of`() {
val distributedService = startNotaryCluster(DISTRIBUTED_SERVICE_NAME, 2).getOrThrow() val distributedService = startNotaryCluster(DISTRIBUTED_SERVICE_NAME, 2).getOrThrow()
@ -182,7 +183,7 @@ class P2PMessagingTest : NodeBasedTest() {
) )
distributedServiceNodes.forEach { distributedServiceNodes.forEach {
val nodeName = it.info.legalIdentity.name val nodeName = it.info.chooseIdentity().name
it.network.addMessageHandler(dummyTopic) { netMessage, _ -> it.network.addMessageHandler(dummyTopic) { netMessage, _ ->
crashingNodes.requestsReceived.incrementAndGet() crashingNodes.requestsReceived.incrementAndGet()
crashingNodes.firstRequestReceived.countDown() 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.crypto.random63BitValue
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.utilities.NonEmptySet
import net.corda.core.internal.cert import net.corda.core.internal.cert
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.seconds import net.corda.core.utilities.seconds
@ -44,7 +43,7 @@ class P2PSecurityTest : NodeBasedTest() {
@Test @Test
fun `register with the network map service using a legal name different from the TLS CN`() { 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 // Register with the network map using a different legal name
val response = it.registerWithNetworkMap(DUMMY_BANK_B.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 // 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( val config = testNodeConfiguration(
baseDirectory = baseDirectory(legalName), baseDirectory = baseDirectory(legalName),
myLegalName = legalName).also { 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 config.configureWithDevSSLCertificate() // This creates the node's TLS cert with the CN as the legal name
return SimpleNode(config, trustRoot = trustRoot).apply { start() } return SimpleNode(config, trustRoot = trustRoot).apply { start() }
@ -68,7 +67,7 @@ class P2PSecurityTest : NodeBasedTest() {
private fun SimpleNode.registerWithNetworkMap(registrationName: CordaX500Name): CordaFuture<NetworkMapService.RegistrationResponse> { private fun SimpleNode.registerWithNetworkMap(registrationName: CordaX500Name): CordaFuture<NetworkMapService.RegistrationResponse> {
val legalIdentity = getTestPartyAndCertificate(registrationName, identity.public) 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 registration = NodeRegistration(nodeInfo, System.currentTimeMillis(), AddOrRemove.ADD, Instant.MAX)
val request = RegistrationRequest(registration.toWire(keyService, identity.public), network.myAddress) val request = RegistrationRequest(registration.toWire(keyService, identity.public), network.myAddress)
return network.sendRequest<NetworkMapService.RegistrationResponse>(NetworkMapService.REGISTER_TOPIC, request, networkMapNode.network.myAddress) return network.sendRequest<NetworkMapService.RegistrationResponse>(NetworkMapService.REGISTER_TOPIC, request, networkMapNode.network.myAddress)

View File

@ -22,6 +22,7 @@ import net.corda.node.services.FlowPermissions
import net.corda.node.services.transactions.SimpleNotaryService import net.corda.node.services.transactions.SimpleNotaryService
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import org.junit.Test import org.junit.Test
import java.lang.management.ManagementFactory import java.lang.management.ManagementFactory
@ -40,7 +41,7 @@ class NodeStatePersistenceTests {
startNode(providedName = DUMMY_NOTARY.name, advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type))).getOrThrow() startNode(providedName = DUMMY_NOTARY.name, advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type))).getOrThrow()
var nodeHandle = startNode(rpcUsers = listOf(user)).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 { nodeHandle.rpcClientToNode().start(user.username, user.password).use {
it.proxy.startFlow(::SendMessageFlow, message).returnValue.getOrThrow() it.proxy.startFlow(::SendMessageFlow, message).returnValue.getOrThrow()
} }
@ -139,7 +140,7 @@ class SendMessageFlow(private val message: Message) : FlowLogic<SignedTransactio
progressTracker.currentStep = GENERATING_TRANSACTION 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 txCommand = Command(MessageContract.Commands.Send(), messageState.participants.map { it.owningKey })
val txBuilder = TransactionBuilder(notary).withItems(StateAndContract(messageState, MESSAGE_CONTRACT_PROGRAM_ID), txCommand) 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 protected val services: ServiceHubInternal get() = _services
private lateinit var _services: ServiceHubInternalImpl private lateinit var _services: ServiceHubInternalImpl
lateinit var legalIdentity: PartyAndCertificate
protected lateinit var info: NodeInfo protected lateinit var info: NodeInfo
protected lateinit var checkpointStorage: CheckpointStorage protected lateinit var checkpointStorage: CheckpointStorage
protected lateinit var smm: StateMachineManager protected lateinit var smm: StateMachineManager
@ -380,7 +381,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
_services = ServiceHubInternalImpl() _services = ServiceHubInternalImpl()
attachments = NodeAttachmentService(services.monitoringService.metrics) attachments = NodeAttachmentService(services.monitoringService.metrics)
cordappProvider = CordappProvider(attachments, makeCordappLoader()) cordappProvider = CordappProvider(attachments, makeCordappLoader())
val legalIdentity = obtainIdentity() legalIdentity = obtainIdentity()
network = makeMessagingService(legalIdentity) network = makeMessagingService(legalIdentity)
info = makeInfo(legalIdentity) info = makeInfo(legalIdentity)
@ -410,9 +411,10 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
private fun makeInfo(legalIdentity: PartyAndCertificate): NodeInfo { private fun makeInfo(legalIdentity: PartyAndCertificate): NodeInfo {
val advertisedServiceEntries = makeServiceEntries() 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. 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" "Initial network map address must indicate a node that provides a network map service"
} }
val address: SingleMessageRecipient = networkMapAddress ?: 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. // Register for updates, even if we're the one running the network map.
return sendNetworkMapRegistration(address).flatMap { (error) -> return sendNetworkMapRegistration(address).flatMap { (error) ->
check(error == null) { "Unable to register with the network map service: $error" } check(error == null) { "Unable to register with the network map service: $error" }
@ -534,7 +536,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
val instant = platformClock.instant() val instant = platformClock.instant()
val expires = instant + NetworkMapService.DEFAULT_EXPIRATION_PERIOD val expires = instant + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
val reg = NodeRegistration(info, info.serial, ADD, expires) 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) 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) val caCertificates: Array<X509Certificate> = listOf(legalIdentity.certificate, clientCa?.certificate?.cert)
.filterNotNull() .filterNotNull()
.toTypedArray() .toTypedArray()
val service = PersistentIdentityService(setOf(info.legalIdentityAndCert), trustRoot = trustRoot, caCertificates = *caCertificates) val service = PersistentIdentityService(info.legalIdentitiesAndCerts.toSet(), trustRoot = trustRoot, caCertificates = *caCertificates)
services.networkMapCache.partyNodes.forEach { service.verifyAndRegisterIdentity(it.legalIdentityAndCert) } services.networkMapCache.partyNodes.forEach { it.legalIdentitiesAndCerts.forEach { service.verifyAndRegisterIdentity(it) } }
services.networkMapCache.changed.subscribe { mapChange -> services.networkMapCache.changed.subscribe { mapChange ->
// TODO how should we handle network map removal // TODO how should we handle network map removal
if (mapChange is MapChange.Added) { if (mapChange is MapChange.Added) {
service.verifyAndRegisterIdentity(mapChange.node.legalIdentityAndCert) mapChange.node.legalIdentitiesAndCerts.forEach {
service.verifyAndRegisterIdentity(it)
}
} }
} }
return service return service
@ -712,7 +716,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
makeIdentityService( makeIdentityService(
trustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA), trustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA),
caKeyStore.certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA), caKeyStore.certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA),
info.legalIdentityAndCert) legalIdentity)
} }
override val attachments: AttachmentStorage get() = this@AbstractNode.attachments override val attachments: AttachmentStorage get() = this@AbstractNode.attachments
override val networkService: MessagingService get() = network 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") return cordappServices.getInstance(type) ?: throw IllegalArgumentException("Corda service ${type.name} does not exist")
} }
override fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator): FlowStateMachineImpl<T> { override fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate?): FlowStateMachineImpl<T> {
return serverThread.fetchFrom { smm.add(logic, flowInitiator) } 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<*>? { 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.AbstractParty
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.messaging.* import net.corda.core.messaging.*
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.node.services.NetworkMapCache import net.corda.core.node.services.NetworkMapCache
@ -110,7 +111,7 @@ class CordaRPCOpsImpl(
} }
} }
override fun nodeIdentity(): NodeInfo { override fun nodeInfo(): NodeInfo {
return services.myInfo return services.myInfo
} }
@ -142,10 +143,11 @@ class CordaRPCOpsImpl(
private fun <T> startFlow(logicType: Class<out FlowLogic<T>>, args: Array<out Any?>): FlowStateMachineImpl<T> { 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" } 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() val rpcContext = getRpcContext()
rpcContext.requirePermission(startFlowPermission(logicType)) rpcContext.requirePermission(startFlowPermission(logicType))
val currentUser = FlowInitiator.RPC(rpcContext.currentUser.username) 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 { override fun attachmentExists(id: SecureHash): Boolean {

View File

@ -96,7 +96,7 @@ open class NodeStartup(val args: Array<String>) {
printPluginsAndServices(node.internals) printPluginsAndServices(node.internals)
node.internals.nodeReadyFuture.thenMatch({ node.internals.nodeReadyFuture.thenMatch({
val elapsed = (System.currentTimeMillis() - startTime) / 10 / 100.0 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") Node.printBasicNodeInfo("Node for \"$name\" started up and registered in $elapsed sec")
// Don't start the shell if there's no console attached. // 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 { override fun call(): Unit {
val revocationEnabled = false val revocationEnabled = false
progressTracker.currentStep = SENDING_KEY 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 -> sendAndReceive<PartyAndCertificate>(otherSide, legalIdentityAnonymous).unwrap { confidentialIdentity ->
SwapIdentitiesFlow.validateAndRegisterIdentity(serviceHub.identityService, otherSide, 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.FlowInitiator
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StateMachineRunId 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.FlowStateMachine
import net.corda.core.internal.VisibleForTesting import net.corda.core.internal.VisibleForTesting
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed
@ -29,9 +31,9 @@ interface NetworkMapCacheInternal : NetworkMapCache {
/** /**
* Deregister from updates from the given map service. * Deregister from updates from the given map service.
* @param network the network messaging 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 * 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. * 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]. * @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. * 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( fun <T> invokeFlowAsync(
logicType: Class<out FlowLogic<T>>, logicType: Class<out FlowLogic<T>>,
flowInitiator: FlowInitiator, flowInitiator: FlowInitiator,
me: PartyAndCertificate? = null,
vararg args: Any?): FlowStateMachineImpl<T> { vararg args: Any?): FlowStateMachineImpl<T> {
val logicRef = FlowLogicRefFactoryImpl.createForRPC(logicType, *args) val logicRef = FlowLogicRefFactoryImpl.createForRPC(logicType, *args)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val logic = FlowLogicRefFactoryImpl.toFlowLogic(logicRef) as FlowLogic<T> val logic = FlowLogicRefFactoryImpl.toFlowLogic(logicRef) as FlowLogic<T>
return startFlow(logic, flowInitiator) return startFlow(logic, flowInitiator, me)
} }
fun getFlowFactory(initiatingFlowClass: Class<out FlowLogic<*>>): InitiatedFlowFactory<*>? 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.crypto.toStringShort
import net.corda.core.identity.* import net.corda.core.identity.*
import net.corda.core.internal.cert 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.IdentityService
import net.corda.core.node.services.UnknownAnonymousPartyException import net.corda.core.node.services.UnknownAnonymousPartyException
import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.SingletonSerializeAsToken
@ -112,7 +113,16 @@ class PersistentIdentityService(identities: Iterable<PartyAndCertificate> = empt
@Throws(CertificateExpiredException::class, CertificateNotYetValidException::class, InvalidAlgorithmParameterException::class) @Throws(CertificateExpiredException::class, CertificateNotYetValidException::class, InvalidAlgorithmParameterException::class)
override fun verifyAndRegisterIdentity(identity: PartyAndCertificate): PartyAndCertificate? { override fun verifyAndRegisterIdentity(identity: PartyAndCertificate): PartyAndCertificate? {
// Validate the chain first, before we do anything clever with it // 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") log.info("Registering identity $identity")
val key = mapToKey(identity) val key = mapToKey(identity)

View File

@ -131,7 +131,7 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
if (!running) { if (!running) {
configureAndStartServer() configureAndStartServer()
// Deploy bridge to the network map service // 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) } networkChangeHandle = networkMapCache.changed.subscribe { updateBridgesOnNetworkChange(it) }
running = true running = true
} }
@ -295,36 +295,24 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
private fun deployBridgesFromNewQueue(queueName: String) { private fun deployBridgesFromNewQueue(queueName: String) {
log.debug { "Queue created: $queueName, deploying bridge(s)" } log.debug { "Queue created: $queueName, deploying bridge(s)" }
fun deployBridgeToPeer(nodeInfo: NodeInfo) { fun deployBridgeToPeer(nodeInfo: NodeInfo) {
log.debug("Deploying bridge for $queueName to $nodeInfo") log.debug("Deploying bridge for $queueName to $nodeInfo")
val address = nodeInfo.addresses.first() // TODO Load balancing. val address = nodeInfo.addresses.first()
deployBridge(queueName, address, nodeInfo.legalIdentity.name) deployBridge(queueName, address, nodeInfo.legalIdentitiesAndCerts.map { it.name }.toSet())
} }
when { if (queueName.startsWith(PEERS_PREFIX)) {
queueName.startsWith(PEERS_PREFIX) -> try { try {
val identity = parsePublicKeyBase58(queueName.substring(PEERS_PREFIX.length)) val identity = parsePublicKeyBase58(queueName.substring(PEERS_PREFIX.length))
val nodeInfo = networkMapCache.getNodeByLegalIdentityKey(identity) val nodeInfos = networkMapCache.getNodesByLegalIdentityKey(identity)
if (nodeInfo != null) { if (nodeInfos.isNotEmpty()) {
deployBridgeToPeer(nodeInfo) nodeInfos.forEach { deployBridgeToPeer(it) }
} else { } else {
log.error("Queue created for a peer that we don't know from the network map: $queueName") log.error("Queue created for a peer that we don't know from the network map: $queueName")
} }
} catch (e: AddressFormatException) { } catch (e: AddressFormatException) {
log.error("Flow violation: Could not parse peer queue name as Base 58: $queueName") 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) { private fun updateBridgesOnNetworkChange(change: MapChange) {
log.debug { "Updating bridges on network map change: ${change.node}" } log.debug { "Updating bridges on network map change: ${change.node}" }
fun gatherAddresses(node: NodeInfo): Sequence<ArtemisPeerAddress> { fun gatherAddresses(node: NodeInfo): Sequence<ArtemisPeerAddress> {
val peerAddress = getArtemisPeerAddress(node) val address = node.addresses.first()
val addresses = mutableListOf(peerAddress) return node.legalIdentitiesAndCerts.map { getArtemisPeerAddress(it.party, address, config.networkMapService?.legalName) }.asSequence()
node.advertisedServices.mapTo(addresses) { NodeAddress.asService(it.identity.owningKey, peerAddress.hostAndPort) }
return addresses.asSequence()
} }
fun deployBridges(node: NodeInfo) { fun deployBridges(node: NodeInfo) {
gatherAddresses(node) gatherAddresses(node)
.filter { queueExists(it.queueName) && !bridgeExists(it.bridgeName) } .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) { fun destroyBridges(node: NodeInfo) {
@ -372,8 +358,8 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
} }
} }
private fun deployBridge(address: ArtemisPeerAddress, legalName: CordaX500Name) { private fun deployBridge(address: ArtemisPeerAddress, legalNames: Set<CordaX500Name>) {
deployBridge(address.queueName, address.hostAndPort, legalName) deployBridge(address.queueName, address.hostAndPort, legalNames)
} }
private fun createTcpTransport(connectionDirection: ConnectionDirection, host: String, port: Int, enableSSL: Boolean = true) = 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 * as defined by ArtemisAddress.queueName. A bridge is then created to forward messages from this queue to the node's
* P2P address. * 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( val connectionDirection = ConnectionDirection.Outbound(
connectorFactoryClassName = VerifyingNettyConnectorFactory::class.java.name, connectorFactoryClassName = VerifyingNettyConnectorFactory::class.java.name,
expectedCommonName = legalName expectedCommonNames = legalNames
) )
val tcpTransport = createTcpTransport(connectionDirection, target.host, target.port) val tcpTransport = createTcpTransport(connectionDirection, target.host, target.port)
tcpTransport.params[ArtemisMessagingServer::class.java.name] = this 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" private fun getBridgeName(queueName: String, hostAndPort: NetworkHostAndPort): String = "$queueName -> $hostAndPort"
// This is called on one of Artemis' background threads // 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) 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! // 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")) _networkMapConnectionFuture!!.setException(IOException("${config.networkMapService} failed host verification check"))
} }
@ -492,7 +478,8 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>,
override fun createConnection(): Connection? { override fun createConnection(): Connection? {
val connection = super.createConnection() as? NettyConnection val connection = super.createConnection() as? NettyConnection
if (sslEnabled && connection != null) { 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 { try {
val session = connection.channel val session = connection.channel
.pipeline() .pipeline()
@ -500,22 +487,27 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>,
.engine() .engine()
.session .session
// Checks the peer name is the one we are expecting. // 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) val peerLegalName = CordaX500Name.parse(session.peerPrincipal.name)
require(peerLegalName == expectedLegalName) { val expectedLegalName = expectedLegalNames.singleOrNull { it == peerLegalName }
"Peer has wrong CN - expected $expectedLegalName but got $peerLegalName. This is either a fatal " + 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!" "misconfiguration by the remote peer or an SSL man-in-the-middle attack!"
} }
// Make sure certificate has the same name. // Make sure certificate has the same name.
val peerCertificateName = CordaX500Name.build(X500Principal(session.peerCertificateChain[0].subjectDN.name)) val peerCertificateName = CordaX500Name.build(X500Principal(session.peerCertificateChain[0].subjectDN.name))
require(peerCertificateName == expectedLegalName) { 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!" "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) X509Utilities.validateCertificateChain(session.localCertificates.last() as java.security.cert.X509Certificate, *session.peerCertificates)
server.onTcpConnection(peerLegalName) server.onTcpConnection(peerLegalName)
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
connection.close() connection.close()
server.hostVerificationFail(expectedLegalName, e.message) server.hostVerificationFail(expectedLegalNames, e.message)
return null 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. * 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) { override val myAddress: SingleMessageRecipient = if (myIdentity != null) {
NodeAddress.asPeer(myIdentity, advertisedAddress) NodeAddress.asSingleNode(myIdentity, advertisedAddress)
} else { } else {
NetworkMapAddress(advertisedAddress) 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 { override fun getAddressOfParty(partyInfo: PartyInfo): MessageRecipients {
return when (partyInfo) { return when (partyInfo) {
is PartyInfo.Node -> getArtemisPeerAddress(partyInfo.node) is PartyInfo.SingleNode -> {
is PartyInfo.Service -> ServiceAddress(partyInfo.service.identity.owningKey) 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) logger.error(msg, e)
return RegistrationResponse(msg) return RegistrationResponse(msg)
} }
val node = change.node 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) { if (node.platformVersion < minimumPlatformVersion) {
return RegistrationResponse("Minimum platform version requirement not met: $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 // in on different threads, there is no risk of a race condition while checking
// sequence numbers. // sequence numbers.
val registrationInfo = try { val registrationInfo = try {
nodeRegistrations.compute(node.legalIdentityAndCert) { _, existing: NodeRegistrationInfo? -> nodeRegistrations.compute(identity) { _, existing: NodeRegistrationInfo? ->
require(!((existing == null || existing.reg.type == REMOVE) && change.type == REMOVE)) { require(!((existing == null || existing.reg.type == REMOVE) && change.type == REMOVE)) {
"Attempting to de-register unknown node" "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) { class WireNodeRegistration(raw: SerializedBytes<NodeRegistration>, sig: DigitalSignature.WithKey) : SignedData<NodeRegistration>(raw, sig) {
@Throws(IllegalArgumentException::class) @Throws(IllegalArgumentException::class)
override fun verifyData(data: NodeRegistration) { 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 private var registeredForPush = false
// TODO Small explanation, partyNodes and registeredNodes is left in memory as it was before, because it will be removed in // 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. // 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) override val networkMapNodes: List<NodeInfo> get() = getNodesWithService(NetworkMapService.type)
private val _changed = PublishSubject.create<MapChange>() private val _changed = PublishSubject.create<MapChange>()
// We use assignment here so that multiple subscribers share the same wrapped Observable. // 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?>() private val _registrationFuture = openFuture<Void?>()
override val nodeReady: CordaFuture<Void?> get() = _registrationFuture override val nodeReady: CordaFuture<Void?> get() = _registrationFuture
protected val registeredNodes: MutableMap<PublicKey, NodeInfo> = Collections.synchronizedMap(HashMap())
private var _loadDBSuccess: Boolean = false private var _loadDBSuccess: Boolean = false
override val loadDBSuccess get() = _loadDBSuccess override val loadDBSuccess get() = _loadDBSuccess
@ -76,13 +76,13 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
override fun getPartyInfo(party: Party): PartyInfo? { override fun getPartyInfo(party: Party): PartyInfo? {
val nodes = serviceHub.database.transaction { queryByIdentityKey(party.owningKey) } val nodes = serviceHub.database.transaction { queryByIdentityKey(party.owningKey) }
if (nodes.size == 1 && nodes[0].legalIdentity == party) { if (nodes.size == 1 && party in nodes[0].legalIdentities) {
return PartyInfo.Node(nodes[0]) return PartyInfo.SingleNode(party, nodes[0].addresses)
} }
for (node in nodes) { for (node in nodes) {
for (service in node.advertisedServices) { for (service in node.advertisedServices) {
if (service.identity.party == party) { 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. // 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() } //serviceHub!!.database.transaction { queryByLegalName(principal).firstOrNull() }
override fun getNodeByLegalIdentityKey(identityKey: PublicKey): NodeInfo? = override fun getNodesByLegalIdentityKey(identityKey: PublicKey): List<NodeInfo> =
serviceHub.database.transaction { queryByIdentityKey(identityKey).firstOrNull() } serviceHub.database.transaction { queryByIdentityKey(identityKey) }
override fun getNodeByLegalIdentity(party: AbstractParty): NodeInfo? { override fun getNodeByLegalIdentity(party: AbstractParty): NodeInfo? {
val wellKnownParty = serviceHub.identityService.partyFromAnonymous(party) val wellKnownParty = serviceHub.identityService.partyFromAnonymous(party)
return wellKnownParty?.let { 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) { override fun addNode(node: NodeInfo) {
synchronized(_changed) { 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) { if (previousNode == null) {
serviceHub.database.transaction { serviceHub.database.transaction {
updateInfoDB(node) updateInfoDB(node)
@ -160,7 +160,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
override fun removeNode(node: NodeInfo) { override fun removeNode(node: NodeInfo) {
synchronized(_changed) { synchronized(_changed) {
registeredNodes.remove(node.legalIdentity.owningKey) registeredNodes.remove(node.legalIdentities.first().owningKey)
serviceHub.database.transaction { serviceHub.database.transaction {
removeInfoDB(node) removeInfoDB(node)
changePublisher.onNext(MapChange.Removed(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. * 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 // Fetch the network map and register for updates at the same time
val req = NetworkMapService.SubscribeRequest(false, network.myAddress) val req = NetworkMapService.SubscribeRequest(false, network.myAddress)
// `network.getAddressOfParty(partyInfo)` is a work-around for MockNetwork and InMemoryMessaging to get rid of SingleMessageRecipient in NodeInfo. // `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 { val future = network.sendRequest<SubscribeResponse>(NetworkMapService.SUBSCRIPTION_TOPIC, req, address).map {
if (it.confirmed) Unit else throw NetworkCacheError.DeregistrationFailed() if (it.confirmed) Unit else throw NetworkCacheError.DeregistrationFailed()
} }
@ -255,7 +256,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
session.use { session.use {
val tx = session.beginTransaction() 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? // 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) val nodeInfoEntry = generateMappedObject(nodeInfo)
if (info.isNotEmpty()) { if (info.isNotEmpty()) {
nodeInfoEntry.id = info[0].id nodeInfoEntry.id = info[0].id
@ -268,7 +269,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
private fun removeInfoDB(nodeInfo: NodeInfo) { private fun removeInfoDB(nodeInfo: NodeInfo) {
createSession { createSession {
val info = findByIdentityKey(it, nodeInfo.legalIdentity.owningKey).single() val info = findByIdentityKey(it, nodeInfo.legalIdentitiesAndCerts.first().owningKey).single()
it.remove(info) it.remove(info)
} }
} }
@ -317,9 +318,9 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
return NodeInfoSchemaV1.PersistentNodeInfo( return NodeInfoSchemaV1.PersistentNodeInfo(
id = 0, id = 0,
addresses = nodeInfo.addresses.map { NodeInfoSchemaV1.DBHostAndPort.fromHostAndPort(it) }, addresses = nodeInfo.addresses.map { NodeInfoSchemaV1.DBHostAndPort.fromHostAndPort(it) },
legalIdentitiesAndCerts = nodeInfo.legalIdentitiesAndCerts.map { NodeInfoSchemaV1.DBPartyAndCertificate(it) }.toSet() // TODO Another ugly hack with special first identity...
// TODO It's workaround to keep the main identity, will be removed in future PR getting rid of services. legalIdentitiesAndCerts = nodeInfo.legalIdentitiesAndCerts.mapIndexed { idx, elem ->
+ NodeInfoSchemaV1.DBPartyAndCertificate(nodeInfo.legalIdentityAndCert, isMain = true), NodeInfoSchemaV1.DBPartyAndCertificate(elem, isMain = idx == 0) },
platformVersion = nodeInfo.platformVersion, platformVersion = nodeInfo.platformVersion,
advertisedServices = nodeInfo.advertisedServices.map { NodeInfoSchemaV1.DBServiceEntry(it.serialize().bytes) }, advertisedServices = nodeInfo.advertisedServices.map { NodeInfoSchemaV1.DBServiceEntry(it.serialize().bytes) },
serial = nodeInfo.serial 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.crypto.random63BitValue
import net.corda.core.flows.* import net.corda.core.flows.*
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.* import net.corda.core.internal.*
import net.corda.core.internal.concurrent.OpenFuture import net.corda.core.internal.concurrent.OpenFuture
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, class FlowStateMachineImpl<R>(override val id: StateMachineRunId,
val logic: FlowLogic<R>, val logic: FlowLogic<R>,
scheduler: FiberScheduler, 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 { companion object {
// Used to work around a small limitation in Quasar. // Used to work around a small limitation in Quasar.
private val QUASAR_UNBLOCKER = Fiber::class.staticField<Any>("SERIALIZER_BLOCKER").value 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.FlowException
import net.corda.core.flows.UnexpectedFlowEndException import net.corda.core.flows.UnexpectedFlowEndException
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.castIfPossible import net.corda.core.internal.castIfPossible
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.utilities.UntrustworthyData import net.corda.core.utilities.UntrustworthyData
@ -25,7 +26,9 @@ data class SessionInit(val initiatorSessionId: Long,
val initiatingFlowClass: String, val initiatingFlowClass: String,
val flowVersion: Int, val flowVersion: Int,
val appName: String, 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, data class SessionConfirm(override val initiatorSessionId: Long,
val initiatedSessionId: 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.crypto.random63BitValue
import net.corda.core.flows.* import net.corda.core.flows.*
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.ThreadBox import net.corda.core.internal.ThreadBox
import net.corda.core.internal.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.internal.castIfPossible import net.corda.core.internal.castIfPossible
@ -288,7 +289,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
private fun onSessionMessage(message: ReceivedMessage) { private fun onSessionMessage(message: ReceivedMessage) {
val sessionMessage = message.data.deserialize<SessionMessage>() val sessionMessage = message.data.deserialize<SessionMessage>()
val sender = serviceHub.networkMapCache.getNodeByLegalName(message.peer)?.legalIdentity val sender = serviceHub.networkMapCache.getPeerByLegalName(message.peer)
if (sender != null) { if (sender != null) {
when (sessionMessage) { when (sessionMessage) {
is ExistingSessionMessage -> onExistingSessionMessage(sessionMessage, sender) is ExistingSessionMessage -> onExistingSessionMessage(sessionMessage, sender)
@ -370,7 +371,8 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
session.receivedMessages += ReceivedSessionMessage(sender, SessionData(session.ourSessionId, sessionInit.firstPayload)) session.receivedMessages += ReceivedSessionMessage(sender, SessionData(session.ourSessionId, sessionInit.firstPayload))
} }
openSessions[session.ourSessionId] = session 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.sessionFlow = flow
flowSession.stateMachine = fiber flowSession.stateMachine = fiber
fiber.openSessions[Pair(flow, sender)] = session 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() 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<*>) { private fun initFiber(fiber: FlowStateMachineImpl<*>) {
@ -512,11 +514,11 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
* *
* Note that you must be on the [executor] thread. * 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. // TODO: Check that logic has @Suspendable on its call method.
executor.checkOnThread() executor.checkOnThread()
val fiber = database.transaction { val fiber = database.transaction {
val fiber = createFiber(logic, flowInitiator) val fiber = createFiber(logic, flowInitiator, me ?: serviceHub.myInfo.legalIdentitiesAndCerts.first())
updateCheckpoint(fiber) updateCheckpoint(fiber)
fiber fiber
} }

View File

@ -45,7 +45,7 @@ class CordappSmokeTest {
factory.create(aliceConfig).use { alice -> factory.create(aliceConfig).use { alice ->
alice.connect().use { connectionToAlice -> 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 future = connectionToAlice.proxy.startFlow(::GatherContextsFlow, aliceIdentity).returnValue
val (sessionInitContext, sessionConfirmContext) = future.getOrThrow() val (sessionInitContext, sessionConfirmContext) = future.getOrThrow()
val selfCordappName = selfCordapp.fileName.toString().removeSuffix(".jar") 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.node.services.transactions.SimpleNotaryService
import net.corda.nodeapi.PermissionException import net.corda.nodeapi.PermissionException
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.chooseIdentity
import net.corda.testing.expect import net.corda.testing.expect
import net.corda.testing.expectEvents import net.corda.testing.expectEvents
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
@ -100,7 +101,7 @@ class CordaRPCOpsImplTest {
} }
// Tell the monitoring service node to issue some cash // 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) val result = rpc.startFlow(::CashIssueFlow, Amount(quantity, GBP), ref, notaryNode.info.notaryIdentity)
mockNet.runNetwork() mockNet.runNetwork()
@ -119,7 +120,7 @@ class CordaRPCOpsImplTest {
val anonymisedRecipient = result.returnValue.getOrThrow().recipient!! val anonymisedRecipient = result.returnValue.getOrThrow().recipient!!
val expectedState = Cash.State(Amount(quantity, val expectedState = Cash.State(Amount(quantity,
Issued(aliceNode.info.legalIdentity.ref(ref), GBP)), Issued(aliceNode.info.chooseIdentity().ref(ref), GBP)),
anonymisedRecipient) anonymisedRecipient)
// Query vault via RPC // Query vault via RPC
@ -150,7 +151,7 @@ class CordaRPCOpsImplTest {
mockNet.runNetwork() mockNet.runNetwork()
rpc.startFlow(::CashPaymentFlow, 100.DOLLARS, aliceNode.info.legalIdentity) rpc.startFlow(::CashPaymentFlow, 100.DOLLARS, aliceNode.info.chooseIdentity())
mockNet.runNetwork() mockNet.runNetwork()
@ -184,7 +185,7 @@ class CordaRPCOpsImplTest {
require(stx.tx.outputs.size == 1) require(stx.tx.outputs.size == 1)
val signaturePubKeys = stx.sigs.map { it.by }.toSet() val signaturePubKeys = stx.sigs.map { it.by }.toSet()
// Only Alice signed, as issuer // Only Alice signed, as issuer
val aliceKey = aliceNode.info.legalIdentity.owningKey val aliceKey = aliceNode.info.chooseIdentity().owningKey
require(signaturePubKeys.size <= aliceKey.keys.size) require(signaturePubKeys.size <= aliceKey.keys.size)
require(aliceKey.isFulfilledBy(signaturePubKeys)) 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.crypto.SecureHash
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.FlowStateMachine import net.corda.core.internal.FlowStateMachine
import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.UntrustworthyData
import net.corda.node.services.identity.InMemoryIdentityService import net.corda.node.services.identity.InMemoryIdentityService
import net.corda.node.shell.InteractiveShell 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
import net.corda.testing.MEGA_CORP_IDENTITY import net.corda.testing.MEGA_CORP_IDENTITY
import org.junit.Test import org.junit.Test
@ -31,7 +33,7 @@ class InteractiveShellTest {
override fun call() = a 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 val om = JacksonSupport.createInMemoryMapper(ids, YAMLFactory())
private fun check(input: String, expected: String) { private fun check(input: String, expected: String) {
@ -69,4 +71,4 @@ class InteractiveShellTest {
fun party() = check("party: \"${MEGA_CORP.name}\"", MEGA_CORP.name.toString()) fun party() = check("party: \"${MEGA_CORP.name}\"", MEGA_CORP.name.toString())
class DummyFSM(val logic: FlowA) : FlowStateMachine<Any?> by mock() class DummyFSM(val logic: FlowA) : FlowStateMachine<Any?> by mock()
} }

View File

@ -96,8 +96,8 @@ class TwoPartyTradeFlowTests {
val aliceNode = basketOfNodes.partyNodes[0] val aliceNode = basketOfNodes.partyNodes[0]
val bobNode = basketOfNodes.partyNodes[1] val bobNode = basketOfNodes.partyNodes[1]
val bankNode = basketOfNodes.partyNodes[2] val bankNode = basketOfNodes.partyNodes[2]
val cashIssuer = bankNode.info.legalIdentity.ref(1) val cashIssuer = bankNode.info.chooseIdentity().ref(1)
val cpIssuer = bankNode.info.legalIdentity.ref(1, 2, 3) val cpIssuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
aliceNode.internals.disableDBCloseOnStop() aliceNode.internals.disableDBCloseOnStop()
bobNode.internals.disableDBCloseOnStop() bobNode.internals.disableDBCloseOnStop()
@ -108,8 +108,8 @@ class TwoPartyTradeFlowTests {
} }
val alicesFakePaper = aliceNode.database.transaction { val alicesFakePaper = aliceNode.database.transaction {
fillUpForSeller(false, cpIssuer, aliceNode.info.legalIdentity, fillUpForSeller(false, cpIssuer, aliceNode.info.chooseIdentity(),
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), null, notaryNode.info.notaryIdentity).second 1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notaryNode.info.notaryIdentity).second
} }
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode) insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
@ -144,7 +144,7 @@ class TwoPartyTradeFlowTests {
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name) val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.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() aliceNode.internals.disableDBCloseOnStop()
bobNode.internals.disableDBCloseOnStop() bobNode.internals.disableDBCloseOnStop()
@ -155,8 +155,8 @@ class TwoPartyTradeFlowTests {
} }
val alicesFakePaper = aliceNode.database.transaction { val alicesFakePaper = aliceNode.database.transaction {
fillUpForSeller(false, issuer, aliceNode.info.legalIdentity, fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), null, notaryNode.info.notaryIdentity).second 1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notaryNode.info.notaryIdentity).second
} }
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode) insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
@ -197,21 +197,16 @@ class TwoPartyTradeFlowTests {
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
var bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name) var bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.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 // Let the nodes know about each other - normally the network map would handle this
val allNodes = listOf(notaryNode, aliceNode, bobNode, bankNode) mockNet.registerIdentities()
allNodes.forEach { node ->
node.database.transaction {
allNodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity -> node.services.identityService.verifyAndRegisterIdentity(identity) }
}
}
aliceNode.database.transaction { aliceNode.database.transaction {
aliceNode.services.identityService.verifyAndRegisterIdentity(bobNode.info.legalIdentityAndCert) aliceNode.services.identityService.verifyAndRegisterIdentity(bobNode.info.chooseIdentityAndCert())
} }
bobNode.database.transaction { bobNode.database.transaction {
bobNode.services.identityService.verifyAndRegisterIdentity(aliceNode.info.legalIdentityAndCert) bobNode.services.identityService.verifyAndRegisterIdentity(aliceNode.info.chooseIdentityAndCert())
} }
aliceNode.internals.disableDBCloseOnStop() aliceNode.internals.disableDBCloseOnStop()
bobNode.internals.disableDBCloseOnStop() bobNode.internals.disableDBCloseOnStop()
@ -226,8 +221,8 @@ class TwoPartyTradeFlowTests {
issuedBy = issuer) issuedBy = issuer)
} }
val alicesFakePaper = aliceNode.database.transaction { val alicesFakePaper = aliceNode.database.transaction {
fillUpForSeller(false, issuer, aliceNode.info.legalIdentity, fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), null, notaryNode.info.notaryIdentity).second 1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notaryNode.info.notaryIdentity).second
} }
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode) insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
val aliceFuture = runBuyerAndSeller(notaryNode, aliceNode, bobNode, "alice's paper".outputStateAndRef()).sellerResult 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 aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name) val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
val bankNode = makeNodeWithTracking(notaryNode.network.myAddress, BOC.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() mockNet.runNetwork()
notaryNode.internals.ensureRegistered() notaryNode.internals.ensureRegistered()
val allNodes = listOf(notaryNode, aliceNode, bobNode, bankNode) mockNet.registerIdentities()
allNodes.forEach { node ->
node.database.transaction {
allNodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity -> node.services.identityService.verifyAndRegisterIdentity(identity) }
}
}
ledger(aliceNode.services, initialiseSerialization = false) { ledger(aliceNode.services, initialiseSerialization = false) {
@ -360,12 +350,12 @@ class TwoPartyTradeFlowTests {
attachment(ByteArrayInputStream(stream.toByteArray())) 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 notaryNode.info.notaryIdentity).second
val bobsSignedTxns = insertFakeTransactions(bobsFakeCash, bobNode, notaryNode, bankNode) val bobsSignedTxns = insertFakeTransactions(bobsFakeCash, bobNode, notaryNode, bankNode)
val alicesFakePaper = aliceNode.database.transaction { val alicesFakePaper = aliceNode.database.transaction {
fillUpForSeller(false, issuer, aliceNode.info.legalIdentity, fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), attachmentID, notaryNode.info.notaryIdentity).second 1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), attachmentID, notaryNode.info.notaryIdentity).second
} }
val alicesSignedTxns = insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode) val alicesSignedTxns = insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
@ -446,19 +436,12 @@ class TwoPartyTradeFlowTests {
val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name) val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name) val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
val bankNode = makeNodeWithTracking(notaryNode.network.myAddress, BOC.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() mockNet.runNetwork()
notaryNode.internals.ensureRegistered() notaryNode.internals.ensureRegistered()
val allNodes = listOf(notaryNode, aliceNode, bobNode, bankNode) mockNet.registerIdentities()
allNodes.forEach { node ->
node.database.transaction {
allNodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity ->
node.services.identityService.verifyAndRegisterIdentity(identity)
}
}
}
ledger(aliceNode.services, initialiseSerialization = false) { ledger(aliceNode.services, initialiseSerialization = false) {
// Insert a prospectus type attachment into the commercial paper transaction. // Insert a prospectus type attachment into the commercial paper transaction.
@ -478,8 +461,8 @@ class TwoPartyTradeFlowTests {
insertFakeTransactions(bobsFakeCash, bobNode, notaryNode, bankNode) insertFakeTransactions(bobsFakeCash, bobNode, notaryNode, bankNode)
val alicesFakePaper = aliceNode.database.transaction { val alicesFakePaper = aliceNode.database.transaction {
fillUpForSeller(false, issuer, aliceNode.info.legalIdentity, fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), attachmentID, notaryNode.info.notaryIdentity).second 1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), attachmentID, notaryNode.info.notaryIdentity).second
} }
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode) insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
@ -556,7 +539,7 @@ class TwoPartyTradeFlowTests {
anonymous: Boolean = true): RunResult { anonymous: Boolean = true): RunResult {
val buyerFlows: Observable<out FlowLogic<*>> = buyerNode.internals.registerInitiatedFlow(BuyerAcceptor::class.java) val buyerFlows: Observable<out FlowLogic<*>> = buyerNode.internals.registerInitiatedFlow(BuyerAcceptor::class.java)
val firstBuyerFiber = buyerFlows.toFuture().map { it.stateMachine } 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 val sellerResult = sellerNode.services.startFlow(seller).resultFuture
return RunResult(firstBuyerFiber, sellerResult, seller.stateMachine.id) return RunResult(firstBuyerFiber, sellerResult, seller.stateMachine.id)
} }
@ -569,10 +552,10 @@ class TwoPartyTradeFlowTests {
val anonymous: Boolean) : FlowLogic<SignedTransaction>() { val anonymous: Boolean) : FlowLogic<SignedTransaction>() {
@Suspendable @Suspendable
override fun call(): SignedTransaction { override fun call(): SignedTransaction {
val me = if (anonymous) { val myParty = if (anonymous) {
serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.legalIdentityAndCert, false) serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.chooseIdentityAndCert(), false)
} else { } else {
serviceHub.myInfo.legalIdentityAndCert serviceHub.myInfo.chooseIdentityAndCert()
} }
send(buyer, TestTx(notary.notaryIdentity, price, anonymous)) send(buyer, TestTx(notary.notaryIdentity, price, anonymous))
return subFlow(Seller( return subFlow(Seller(
@ -580,7 +563,7 @@ class TwoPartyTradeFlowTests {
notary, notary,
assetToSell, assetToSell,
price, price,
me)) myParty))
} }
} }
@ -608,25 +591,20 @@ class TwoPartyTradeFlowTests {
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name) val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name) val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.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() mockNet.runNetwork()
notaryNode.internals.ensureRegistered() notaryNode.internals.ensureRegistered()
// Let the nodes know about each other - normally the network map would handle this // Let the nodes know about each other - normally the network map would handle this
val allNodes = listOf(notaryNode, aliceNode, bobNode, bankNode) mockNet.registerIdentities()
allNodes.forEach { node ->
node.database.transaction {
allNodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity -> node.services.identityService.verifyAndRegisterIdentity(identity) }
}
}
val bobsBadCash = bobNode.database.transaction { val bobsBadCash = bobNode.database.transaction {
fillUpForBuyer(bobError, issuer, bobNode.info.legalIdentity, fillUpForBuyer(bobError, issuer, bobNode.info.chooseIdentity(),
notaryNode.info.notaryIdentity).second notaryNode.info.notaryIdentity).second
} }
val alicesFakePaper = aliceNode.database.transaction { 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 1200.DOLLARS `issued by` issuer, null, notaryNode.info.notaryIdentity).second
} }
@ -661,10 +639,14 @@ class TwoPartyTradeFlowTests {
val signed = wtxToSign.map { val signed = wtxToSign.map {
val id = it.id val id = it.id
val sigs = mutableListOf<TransactionSignature>() 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)) sigs.add(notaryNode.services.keyManagementService.sign(SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(notaryNode.services.notaryIdentityKey).schemeNumberID)), notaryNode.services.notaryIdentityKey))
extraSigningNodes.forEach { currentNode -> 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) 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.node.services.transactions.SimpleNotaryService
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.contracts.DUMMY_PROGRAM_ID import net.corda.testing.contracts.DUMMY_PROGRAM_ID
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand import net.corda.testing.dummyCommand
import net.corda.testing.getTestPartyAndCertificate import net.corda.testing.getTestPartyAndCertificate
@ -45,7 +46,7 @@ class NotaryChangeTests {
clientNodeA = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress) clientNodeA = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress)
clientNodeB = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress) clientNodeB = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress)
newNotaryNode = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress, advertisedServices = ServiceInfo(SimpleNotaryService.type)) newNotaryNode = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress, advertisedServices = ServiceInfo(SimpleNotaryService.type))
mockNet.registerIdentities()
mockNet.runNetwork() // Clear network map registration messages mockNet.runNetwork() // Clear network map registration messages
oldNotaryNode.internals.ensureRegistered() oldNotaryNode.internals.ensureRegistered()
} }
@ -133,7 +134,7 @@ class NotaryChangeTests {
} }
private fun issueEncumberedState(node: StartedNode<*>, notaryNode: StartedNode<*>): WireTransaction { 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 notary = notaryNode.info.notaryIdentity
val stateA = DummyContract.SingleOwnerState(Random().nextInt(), owner.party) val stateA = DummyContract.SingleOwnerState(Random().nextInt(), owner.party)
@ -161,7 +162,7 @@ class NotaryChangeTests {
} }
fun issueState(node: StartedNode<*>, notaryNode: StartedNode<*>): StateAndRef<*> { 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 signedByNode = node.services.signInitialTransaction(tx)
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey) val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
node.services.recordTransactions(stx) 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> { fun issueMultiPartyState(nodeA: StartedNode<*>, nodeB: StartedNode<*>, notaryNode: StartedNode<*>): StateAndRef<DummyContract.MultiOwnerState> {
val state = TransactionState(DummyContract.MultiOwnerState(0, 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 tx = TransactionBuilder(notary = notaryNode.info.notaryIdentity).withItems(state, dummyCommand())
val signedByA = nodeA.services.signInitialTransaction(tx) val signedByA = nodeA.services.signInitialTransaction(tx)
val signedByAB = nodeB.services.addSignature(signedByA) val signedByAB = nodeB.services.addSignature(signedByA)
@ -182,7 +183,7 @@ fun issueMultiPartyState(nodeA: StartedNode<*>, nodeB: StartedNode<*>, notaryNod
} }
fun issueInvalidState(node: StartedNode<*>, notary: Party): StateAndRef<*> { 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) tx.setTimeWindow(Instant.now(), 30.seconds)
val stx = node.services.signInitialTransaction(tx) val stx = node.services.signInitialTransaction(tx)
node.services.recordTransactions(stx) node.services.recordTransactions(stx)

View File

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

View File

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

View File

@ -16,7 +16,6 @@ import net.corda.node.utilities.X509Utilities
import net.corda.testing.* import net.corda.testing.*
import org.junit.Test import org.junit.Test
import java.security.cert.CertificateFactory import java.security.cert.CertificateFactory
import javax.security.auth.x500.X500Principal
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith
import kotlin.test.assertNull import kotlin.test.assertNull
@ -27,7 +26,7 @@ import kotlin.test.assertNull
class InMemoryIdentityServiceTests { class InMemoryIdentityServiceTests {
@Test @Test
fun `get all identities`() { fun `get all identities`() {
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate) val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
// Nothing registered, so empty set // Nothing registered, so empty set
assertNull(service.getAllIdentities().firstOrNull()) assertNull(service.getAllIdentities().firstOrNull())
@ -45,7 +44,7 @@ class InMemoryIdentityServiceTests {
@Test @Test
fun `get identity by key`() { fun `get identity by key`() {
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate) val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
assertNull(service.partyFromKey(ALICE_PUBKEY)) assertNull(service.partyFromKey(ALICE_PUBKEY))
service.verifyAndRegisterIdentity(ALICE_IDENTITY) service.verifyAndRegisterIdentity(ALICE_IDENTITY)
assertEquals(ALICE, service.partyFromKey(ALICE_PUBKEY)) assertEquals(ALICE, service.partyFromKey(ALICE_PUBKEY))
@ -54,14 +53,13 @@ class InMemoryIdentityServiceTests {
@Test @Test
fun `get identity by name with no registered identities`() { 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)) assertNull(service.partyFromX500Name(ALICE.name))
} }
@Test @Test
fun `get identity by substring match`() { fun `get identity by substring match`() {
val trustRoot = DUMMY_CA val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
val service = InMemoryIdentityService(trustRoot = trustRoot.certificate)
service.verifyAndRegisterIdentity(ALICE_IDENTITY) service.verifyAndRegisterIdentity(ALICE_IDENTITY)
service.verifyAndRegisterIdentity(BOB_IDENTITY) service.verifyAndRegisterIdentity(BOB_IDENTITY)
val alicente = getTestPartyAndCertificate(CordaX500Name(organisation = "Alicente Worldwide", locality = "London", country = "GB"), generateKeyPair().public) val alicente = getTestPartyAndCertificate(CordaX500Name(organisation = "Alicente Worldwide", locality = "London", country = "GB"), generateKeyPair().public)
@ -73,7 +71,7 @@ class InMemoryIdentityServiceTests {
@Test @Test
fun `get identity by name`() { 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") val identities = listOf("Org A", "Org B", "Org C")
.map { getTestPartyAndCertificate(CordaX500Name(organisation = it, locality = "London", country = "GB"), generateKeyPair().public) } .map { getTestPartyAndCertificate(CordaX500Name(organisation = it, locality = "London", country = "GB"), generateKeyPair().public) }
assertNull(service.partyFromX500Name(identities.first().name)) assertNull(service.partyFromX500Name(identities.first().name))
@ -90,7 +88,7 @@ class InMemoryIdentityServiceTests {
val rootKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val rootKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val rootCert = X509Utilities.createSelfSignedCACertificate(ALICE.name, rootKey) val rootCert = X509Utilities.createSelfSignedCACertificate(ALICE.name, rootKey)
val txKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) 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 // TODO: Generate certificate with an EdDSA key rather than ECDSA
val identity = Party(rootCert.cert) val identity = Party(rootCert.cert)
val txIdentity = AnonymousParty(txKey.public) val txIdentity = AnonymousParty(txKey.public)
@ -107,12 +105,11 @@ class InMemoryIdentityServiceTests {
*/ */
@Test @Test
fun `get anonymous identity by key`() { fun `get anonymous identity by key`() {
val trustRoot = DUMMY_CA val (alice, aliceTxIdentity) = createParty(ALICE.name, DEV_CA)
val (alice, aliceTxIdentity) = createParty(ALICE.name, trustRoot) val (_, bobTxIdentity) = createParty(ALICE.name, DEV_CA)
val (_, bobTxIdentity) = createParty(ALICE.name, trustRoot)
// Now we have identities, construct the service and let it know about both // 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) service.verifyAndRegisterIdentity(aliceTxIdentity)
var actual = service.certificateFromKey(aliceTxIdentity.party.owningKey) var actual = service.certificateFromKey(aliceTxIdentity.party.owningKey)
@ -131,12 +128,11 @@ class InMemoryIdentityServiceTests {
@Test @Test
fun `assert ownership`() { fun `assert ownership`() {
withTestSerialization { withTestSerialization {
val trustRoot = DUMMY_CA val (alice, anonymousAlice) = createParty(ALICE.name, DEV_CA)
val (alice, anonymousAlice) = createParty(ALICE.name, trustRoot) val (bob, anonymousBob) = createParty(BOB.name, DEV_CA)
val (bob, anonymousBob) = createParty(BOB.name, trustRoot)
// Now we have identities, construct the service and let it know about both // 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(anonymousAlice)
service.verifyAndRegisterIdentity(anonymousBob) service.verifyAndRegisterIdentity(anonymousBob)
@ -152,8 +148,8 @@ class InMemoryIdentityServiceTests {
} }
assertFailsWith<IllegalArgumentException> { assertFailsWith<IllegalArgumentException> {
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded) val owningKey = Crypto.decodePublicKey(DEV_CA.certificate.subjectPublicKeyInfo.encoded)
val subject = CordaX500Name.build(X500Principal(trustRoot.certificate.subject.encoded)) val subject = CordaX500Name.build(DEV_CA.certificate.cert.subjectX500Principal)
service.assertOwnership(Party(subject, owningKey), anonymousAlice.party.anonymise()) service.assertOwnership(Party(subject, owningKey), anonymousAlice.party.anonymise())
} }
} }
@ -175,7 +171,7 @@ class InMemoryIdentityServiceTests {
@Test @Test
fun `deanonymising a well known identity`() { fun `deanonymising a well known identity`() {
val expected = ALICE val expected = ALICE
val actual = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate).partyFromAnonymous(expected) val actual = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT).partyFromAnonymous(expected)
assertEquals(expected, actual) 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.core.utilities.getOrThrow
import net.corda.testing.ALICE import net.corda.testing.ALICE
import net.corda.testing.BOB import net.corda.testing.BOB
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After
@ -41,16 +42,16 @@ class NetworkMapCacheTest {
val entropy = BigInteger.valueOf(24012017L) val entropy = BigInteger.valueOf(24012017L)
val nodeA = mockNet.createNode(nodeFactory = MockNetwork.DefaultFactory, legalName = ALICE.name, entropyRoot = entropy, advertisedServices = ServiceInfo(NetworkMapService.type)) 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)) 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() mockNet.runNetwork()
// Node A currently knows only about itself, so this returns node A // 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) nodeA.services.networkMapCache.addNode(nodeB.info)
// The details of node B write over those for node A // 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 @Test
@ -62,7 +63,7 @@ class NetworkMapCacheTest {
val expected = n1.info val expected = n1.info
mockNet.runNetwork() 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) assertEquals(expected, actual)
// TODO: Should have a test case with anonymous lookup // TODO: Should have a test case with anonymous lookup
@ -73,14 +74,16 @@ class NetworkMapCacheTest {
val nodes = mockNet.createSomeNodes(1) val nodes = mockNet.createSomeNodes(1)
val n0 = nodes.mapNode val n0 = nodes.mapNode
val n1 = nodes.partyNodes[0] val n1 = nodes.partyNodes[0]
val n0Identity = n0.info.chooseIdentity()
val n1Identity = n1.info.chooseIdentity()
val node0Cache = n0.services.networkMapCache as PersistentNetworkMapCache val node0Cache = n0.services.networkMapCache as PersistentNetworkMapCache
mockNet.runNetwork() mockNet.runNetwork()
n0.database.transaction { n0.database.transaction {
assertThat(node0Cache.getNodeByLegalIdentity(n1.info.legalIdentity) != null) assertThat(node0Cache.getNodeByLegalIdentity(n1Identity) != null)
node0Cache.removeNode(n1.info) node0Cache.removeNode(n1.info)
assertThat(node0Cache.getNodeByLegalIdentity(n1.info.legalIdentity) == null) assertThat(node0Cache.getNodeByLegalIdentity(n1Identity) == null)
assertThat(node0Cache.getNodeByLegalIdentity(n0.info.legalIdentity) != null) assertThat(node0Cache.getNodeByLegalIdentity(n0Identity) != null)
assertThat(node0Cache.getNodeByLegalName(n1.info.legalIdentity.name) == null) assertThat(node0Cache.getNodeByLegalName(n1Identity.name) == null)
} }
} }
} }

View File

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

View File

@ -14,6 +14,7 @@ import net.corda.testing.ALICE
import net.corda.testing.BOB import net.corda.testing.BOB
import net.corda.testing.CHARLIE import net.corda.testing.CHARLIE
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.node.NodeBasedTest import net.corda.testing.node.NodeBasedTest
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.Before 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 { it.internals.nodeReadyFuture.get() } // Need to wait for network map registration, as these tests are ran without waiting.
nodes.forEach { nodes.forEach {
infos.add(it.info) 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. 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 alice = startNodesWithPort(listOf(ALICE), noNetworkMap = true)[0]
val netCache = alice.services.networkMapCache as PersistentNetworkMapCache val netCache = alice.services.networkMapCache as PersistentNetworkMapCache
alice.database.transaction { alice.database.transaction {
val res = netCache.getNodeByLegalIdentity(alice.info.legalIdentity) val res = netCache.getNodeByLegalIdentity(alice.info.chooseIdentity())
assertEquals(alice.info, res) assertEquals(alice.info, res)
val res2 = netCache.getNodeByLegalName(DUMMY_NOTARY.name) 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 }) assert(NetworkMapService.type !in alice.info.advertisedServices.map { it.info.type })
assertEquals(NullNetworkMapService, alice.inNodeNetworkMapService) assertEquals(NullNetworkMapService, alice.inNodeNetworkMapService)
assertEquals(infos.size, partyNodes.size) 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 @Test
@ -78,7 +79,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
nodes.forEach { nodes.forEach {
val partyNodes = it.services.networkMapCache.partyNodes val partyNodes = it.services.networkMapCache.partyNodes
assertEquals(infos.size, partyNodes.size) 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) checkConnectivity(nodes)
} }
@ -92,7 +93,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
nodes.forEach { nodes.forEach {
val partyNodes = it.services.networkMapCache.partyNodes val partyNodes = it.services.networkMapCache.partyNodes
assertEquals(infos.size, partyNodes.size) 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) checkConnectivity(nodes)
} }
@ -115,20 +116,20 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
// Start 2 nodes pointing at network map, but don't start network map service. // Start 2 nodes pointing at network map, but don't start network map service.
val otherNodes = startNodesWithPort(parties, noNetworkMap = false) val otherNodes = startNodesWithPort(parties, noNetworkMap = false)
otherNodes.forEach { node -> 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. // 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] val charlie = startNodesWithPort(listOf(CHARLIE), noNetworkMap = false)[0]
otherNodes.forEach { 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. // Start Network Map and see that charlie node appears in caches.
val nms = startNodesWithPort(listOf(DUMMY_NOTARY), noNetworkMap = false)[0] val nms = startNodesWithPort(listOf(DUMMY_NOTARY), noNetworkMap = false)[0]
nms.internals.startupComplete.get() nms.internals.startupComplete.get()
assert(nms.inNodeNetworkMapService != NullNetworkMapService) assert(nms.inNodeNetworkMapService != NullNetworkMapService)
assert(infos.any {it.legalIdentity == nms.info.legalIdentity}) assert(infos.any { it.legalIdentities.toSet() == nms.info.legalIdentities.toSet() })
otherNodes.forEach { 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. charlie.internals.nodeReadyFuture.get() // Finish registration.
checkConnectivity(listOf(otherNodes[0], nms)) // Checks connectivity from A to NMS. 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 cacheB = otherNodes[1].services.networkMapCache.partyNodes
val cacheC = charlie.services.networkMapCache.partyNodes val cacheC = charlie.services.networkMapCache.partyNodes
assertEquals(4, cacheC.size) // Charlie fetched data from NetworkMap 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(), cacheB.toSet())
assertEquals(cacheA.toSet(), cacheC.toSet()) assertEquals(cacheA.toSet(), cacheC.toSet())
} }
@ -163,7 +164,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
nodes.forEach { node1 -> nodes.forEach { node1 ->
nodes.forEach { node2 -> nodes.forEach { node2 ->
node2.internals.registerInitiatedFlow(SendBackFlow::class.java) 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!") 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.node.services.NotifyTransactionHandler
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.MEGA_CORP import net.corda.testing.MEGA_CORP
import net.corda.testing.chooseIdentity
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After
@ -45,8 +46,8 @@ class DataVendingServiceTests {
val nodes = mockNet.createSomeNodes(2) val nodes = mockNet.createSomeNodes(2)
val vaultServiceNode = nodes.partyNodes[0] val vaultServiceNode = nodes.partyNodes[0]
val registerNode = nodes.partyNodes[1] val registerNode = nodes.partyNodes[1]
val beneficiary = vaultServiceNode.info.legalIdentity val beneficiary = vaultServiceNode.info.chooseIdentity()
val deposit = registerNode.info.legalIdentity.ref(1) val deposit = registerNode.info.chooseIdentity().ref(1)
mockNet.runNetwork() mockNet.runNetwork()
// Generate an issuance transaction // Generate an issuance transaction
@ -75,7 +76,7 @@ class DataVendingServiceTests {
val nodes = mockNet.createSomeNodes(2) val nodes = mockNet.createSomeNodes(2)
val vaultServiceNode = nodes.partyNodes[0] val vaultServiceNode = nodes.partyNodes[0]
val registerNode = nodes.partyNodes[1] val registerNode = nodes.partyNodes[1]
val beneficiary = vaultServiceNode.info.legalIdentity val beneficiary = vaultServiceNode.info.chooseIdentity()
val deposit = MEGA_CORP.ref(1) val deposit = MEGA_CORP.ref(1)
mockNet.runNetwork() mockNet.runNetwork()
@ -97,7 +98,7 @@ class DataVendingServiceTests {
private fun StartedNode<*>.sendNotifyTx(tx: SignedTransaction, walletServiceNode: StartedNode<*>) { private fun StartedNode<*>.sendNotifyTx(tx: SignedTransaction, walletServiceNode: StartedNode<*>) {
walletServiceNode.internals.registerInitiatedFlow(InitiateNotifyTxFlow::class.java) walletServiceNode.internals.registerInitiatedFlow(InitiateNotifyTxFlow::class.java)
services.startFlow(NotifyTxFlow(walletServiceNode.info.legalIdentity, tx)) services.startFlow(NotifyTxFlow(walletServiceNode.info.chooseIdentity(), tx))
mockNet.runNetwork() mockNet.runNetwork()
} }

View File

@ -94,14 +94,7 @@ class FlowFrameworkTests {
mockNet.runNetwork() mockNet.runNetwork()
// We don't create a network map, so manually handle registrations // We don't create a network map, so manually handle registrations
val nodes = listOf(node1, node2, notary1, notary2) mockNet.registerIdentities()
nodes.forEach { node ->
node.database.transaction {
nodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity ->
node.services.identityService.verifyAndRegisterIdentity(identity)
}
}
}
} }
@After @After
@ -128,7 +121,7 @@ class FlowFrameworkTests {
@Test @Test
fun `exception while fiber suspended`() { fun `exception while fiber suspended`() {
node2.registerFlowFactory(ReceiveFlow::class) { SendFlow("Hello", it) } 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 val fiber = node1.services.startFlow(flow) as FlowStateMachineImpl
// Before the flow runs change the suspend action to throw an exception // Before the flow runs change the suspend action to throw an exception
val exceptionDuringSuspend = Exception("Thrown during suspend") val exceptionDuringSuspend = Exception("Thrown during suspend")
@ -147,7 +140,7 @@ class FlowFrameworkTests {
@Test @Test
fun `flow restarted just after receiving payload`() { fun `flow restarted just after receiving payload`() {
node2.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() } 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 // We push through just enough messages to get only the payload sent
node2.pumpReceive() node2.pumpReceive()
@ -199,7 +192,7 @@ class FlowFrameworkTests {
@Test @Test
fun `flow loaded from checkpoint will respond to messages from before start`() { fun `flow loaded from checkpoint will respond to messages from before start`() {
node1.registerFlowFactory(ReceiveFlow::class) { SendFlow("Hello", it) } 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. // Make sure the add() has finished initial processing.
node2.smm.executor.flush() node2.smm.executor.flush()
node2.internals.disableDBCloseOnStop() node2.internals.disableDBCloseOnStop()
@ -221,7 +214,7 @@ class FlowFrameworkTests {
mockNet.runNetwork() mockNet.runNetwork()
// Kick off first send and receive // 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 { node2.database.transaction {
assertEquals(1, node2.checkpointStorage.checkpoints().size) assertEquals(1, node2.checkpointStorage.checkpoints().size)
} }
@ -266,7 +259,7 @@ class FlowFrameworkTests {
node2.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() } node2.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() }
node3.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() } node3.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() }
val payload = "Hello World" 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() mockNet.runNetwork()
val node2Flow = node2.getSingleFlow<ReceiveFlow>().first val node2Flow = node2.getSingleFlow<ReceiveFlow>().first
val node3Flow = node3.getSingleFlow<ReceiveFlow>().first val node3Flow = node3.getSingleFlow<ReceiveFlow>().first
@ -299,7 +292,7 @@ class FlowFrameworkTests {
val node3Payload = "Test 2" val node3Payload = "Test 2"
node2.registerFlowFactory(ReceiveFlow::class) { SendFlow(node2Payload, it) } node2.registerFlowFactory(ReceiveFlow::class) { SendFlow(node2Payload, it) }
node3.registerFlowFactory(ReceiveFlow::class) { SendFlow(node3Payload, 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.services.startFlow(multiReceiveFlow)
node1.internals.acceptableLiveFiberCountOnStop = 1 node1.internals.acceptableLiveFiberCountOnStop = 1
mockNet.runNetwork() mockNet.runNetwork()
@ -324,7 +317,7 @@ class FlowFrameworkTests {
@Test @Test
fun `both sides do a send as their first IO request`() { fun `both sides do a send as their first IO request`() {
node2.registerFlowFactory(PingPongFlow::class) { PingPongFlow(it, 20L) } 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() mockNet.runNetwork()
assertSessionTransfers( assertSessionTransfers(
@ -347,13 +340,13 @@ class FlowFrameworkTests {
notary1.info.notaryIdentity)).resultFuture.getOrThrow() notary1.info.notaryIdentity)).resultFuture.getOrThrow()
// We pay a couple of times, the notary picking should go round robin // We pay a couple of times, the notary picking should go round robin
for (i in 1..3) { 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() mockNet.runNetwork()
flow.resultFuture.getOrThrow() flow.resultFuture.getOrThrow()
} }
val endpoint = mockNet.messagingNetwork.endpoint(notary1.network.myAddress as InMemoryMessagingNetwork.PeerHandle)!! val endpoint = mockNet.messagingNetwork.endpoint(notary1.network.myAddress as InMemoryMessagingNetwork.PeerHandle)!!
val party1Info = notary1.services.networkMapCache.getPartyInfo(notary1.info.notaryIdentity)!! val party1Info = notary1.services.networkMapCache.getPartyInfo(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)!!) val notary1Address: MessageRecipients = endpoint.getAddressOfParty(notary1.services.networkMapCache.getPartyInfo(notary1.info.notaryIdentity)!!)
assertThat(notary1Address).isInstanceOf(InMemoryMessagingNetwork.ServiceHandle::class.java) assertThat(notary1Address).isInstanceOf(InMemoryMessagingNetwork.ServiceHandle::class.java)
assertEquals(notary1Address, endpoint.getAddressOfParty(notary2.services.networkMapCache.getPartyInfo(notary2.info.notaryIdentity)!!)) assertEquals(notary1Address, endpoint.getAddressOfParty(notary2.services.networkMapCache.getPartyInfo(notary2.info.notaryIdentity)!!))
@ -396,7 +389,7 @@ class FlowFrameworkTests {
@Test @Test
fun `other side ends before doing expected send`() { fun `other side ends before doing expected send`() {
node2.registerFlowFactory(ReceiveFlow::class) { NoOpFlow() } 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() mockNet.runNetwork()
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy { assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
resultFuture.getOrThrow() resultFuture.getOrThrow()
@ -409,7 +402,7 @@ class FlowFrameworkTests {
val sessionEndReceived = Semaphore(0) val sessionEndReceived = Semaphore(0)
receivedSessionMessagesObservable().filter { it.message is SessionEnd }.subscribe { sessionEndReceived.release() } receivedSessionMessagesObservable().filter { it.message is SessionEnd }.subscribe { sessionEndReceived.release() }
val resultFuture = node1.services.startFlow( val resultFuture = node1.services.startFlow(
WaitForOtherSideEndBeforeSendAndReceive(node2.info.legalIdentity, sessionEndReceived)).resultFuture WaitForOtherSideEndBeforeSendAndReceive(node2.info.chooseIdentity(), sessionEndReceived)).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy { assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
resultFuture.getOrThrow() resultFuture.getOrThrow()
@ -436,7 +429,7 @@ class FlowFrameworkTests {
} }
val erroringFlowSteps = erroringFlowFuture.flatMap { it.progressSteps } val erroringFlowSteps = erroringFlowFuture.flatMap { it.progressSteps }
val receiveFlow = ReceiveFlow(node2.info.legalIdentity) val receiveFlow = ReceiveFlow(node2.info.chooseIdentity())
val receiveFlowSteps = receiveFlow.progressSteps val receiveFlowSteps = receiveFlow.progressSteps
val receiveFlowResult = node1.services.startFlow(receiveFlow).resultFuture val receiveFlowResult = node1.services.startFlow(receiveFlow).resultFuture
@ -470,7 +463,7 @@ class FlowFrameworkTests {
} }
val erroringFlowSteps = erroringFlow.flatMap { it.progressSteps } 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() mockNet.runNetwork()
@ -504,8 +497,8 @@ class FlowFrameworkTests {
mockNet.runNetwork() mockNet.runNetwork()
node3.registerFlowFactory(ReceiveFlow::class) { ExceptionFlow { MyFlowException("Chain") } } node3.registerFlowFactory(ReceiveFlow::class) { ExceptionFlow { MyFlowException("Chain") } }
node2.registerFlowFactory(ReceiveFlow::class) { ReceiveFlow(node3.info.legalIdentity) } node2.registerFlowFactory(ReceiveFlow::class) { ReceiveFlow(node3.info.chooseIdentity()) }
val receivingFiber = node1.services.startFlow(ReceiveFlow(node2.info.legalIdentity)) val receivingFiber = node1.services.startFlow(ReceiveFlow(node2.info.chooseIdentity()))
mockNet.runNetwork() mockNet.runNetwork()
assertThatExceptionOfType(MyFlowException::class.java) assertThatExceptionOfType(MyFlowException::class.java)
.isThrownBy { receivingFiber.resultFuture.getOrThrow() } .isThrownBy { receivingFiber.resultFuture.getOrThrow() }
@ -524,7 +517,7 @@ class FlowFrameworkTests {
.map { it.stateMachine } .map { it.stateMachine }
node3.registerFlowFactory(ReceiveFlow::class) { ExceptionFlow { MyFlowException("Nothing useful") } } 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() 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 // 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") } 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() mockNet.runNetwork()
assertThat(resultFuture.getOrThrow()).isEqualTo("Hello") assertThat(resultFuture.getOrThrow()).isEqualTo("Hello")
} }
@ -584,7 +577,7 @@ class FlowFrameworkTests {
@Test @Test
fun `serialisation issue in counterparty`() { fun `serialisation issue in counterparty`() {
node2.registerFlowFactory(ReceiveFlow::class) { SendFlow(NonSerialisableData(1), it) } 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() mockNet.runNetwork()
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy { assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
result.getOrThrow() result.getOrThrow()
@ -596,7 +589,7 @@ class FlowFrameworkTests {
node2.registerFlowFactory(ReceiveFlow::class) { node2.registerFlowFactory(ReceiveFlow::class) {
ExceptionFlow { NonSerialisableFlowException(NonSerialisableData(1)) } 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() mockNet.runNetwork()
assertThatExceptionOfType(FlowException::class.java).isThrownBy { assertThatExceptionOfType(FlowException::class.java).isThrownBy {
result.getOrThrow() result.getOrThrow()
@ -607,13 +600,13 @@ class FlowFrameworkTests {
fun `wait for transaction`() { fun `wait for transaction`() {
val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity) val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity)
.addOutputState(DummyState(), DUMMY_PROGRAM_ID) .addOutputState(DummyState(), DUMMY_PROGRAM_ID)
.addCommand(dummyCommand(node1.services.legalIdentityKey)) .addCommand(dummyCommand(node1.info.chooseIdentity().owningKey))
val stx = node1.services.signInitialTransaction(ptx) val stx = node1.services.signInitialTransaction(ptx)
val committerFiber = node1.registerFlowFactory(WaitingFlows.Waiter::class) { val committerFiber = node1.registerFlowFactory(WaitingFlows.Waiter::class) {
WaitingFlows.Committer(it) WaitingFlows.Committer(it)
}.map { it.stateMachine } }.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() mockNet.runNetwork()
assertThat(waiterStx.getOrThrow()).isEqualTo(committerFiber.getOrThrow().resultFuture.getOrThrow()) assertThat(waiterStx.getOrThrow()).isEqualTo(committerFiber.getOrThrow().resultFuture.getOrThrow())
} }
@ -628,7 +621,7 @@ class FlowFrameworkTests {
node1.registerFlowFactory(WaitingFlows.Waiter::class) { node1.registerFlowFactory(WaitingFlows.Waiter::class) {
WaitingFlows.Committer(it) { throw Exception("Error") } 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() mockNet.runNetwork()
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy { assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
waiter.getOrThrow() waiter.getOrThrow()
@ -639,13 +632,13 @@ class FlowFrameworkTests {
fun `verify vault query service is tokenizable by force checkpointing within a flow`() { fun `verify vault query service is tokenizable by force checkpointing within a flow`() {
val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity) val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity)
.addOutputState(DummyState(), DUMMY_PROGRAM_ID) .addOutputState(DummyState(), DUMMY_PROGRAM_ID)
.addCommand(dummyCommand(node1.services.legalIdentityKey)) .addCommand(dummyCommand(node1.info.chooseIdentity().owningKey))
val stx = node1.services.signInitialTransaction(ptx) val stx = node1.services.signInitialTransaction(ptx)
node1.registerFlowFactory(VaultQueryFlow::class) { node1.registerFlowFactory(VaultQueryFlow::class) {
WaitingFlows.Committer(it) 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() mockNet.runNetwork()
assertThat(result.getOrThrow()).isEmpty() assertThat(result.getOrThrow()).isEmpty()
@ -654,14 +647,14 @@ class FlowFrameworkTests {
@Test @Test
fun `customised client flow`() { fun `customised client flow`() {
val receiveFlowFuture = node2.registerFlowFactory(SendFlow::class) { ReceiveFlow(it) } 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() mockNet.runNetwork()
assertThat(receiveFlowFuture.getOrThrow().receivedPayloads).containsOnly("Hello") assertThat(receiveFlowFuture.getOrThrow().receivedPayloads).containsOnly("Hello")
} }
@Test @Test
fun `customised client flow which has annotated @InitiatingFlow again`() { 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() mockNet.runNetwork()
assertThatExceptionOfType(IllegalArgumentException::class.java).isThrownBy { assertThatExceptionOfType(IllegalArgumentException::class.java).isThrownBy {
result.getOrThrow() result.getOrThrow()
@ -671,7 +664,7 @@ class FlowFrameworkTests {
@Test @Test
fun `upgraded initiating flow`() { fun `upgraded initiating flow`() {
node2.registerFlowFactory(UpgradedFlow::class, initiatedFlowVersion = 1) { SendFlow("Old initiated", it) } 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() mockNet.runNetwork()
assertThat(receivedSessionMessages).startsWith( assertThat(receivedSessionMessages).startsWith(
node1 sent sessionInit(UpgradedFlow::class, flowVersion = 2) to node2, node1 sent sessionInit(UpgradedFlow::class, flowVersion = 2) to node2,
@ -685,19 +678,19 @@ class FlowFrameworkTests {
@Test @Test
fun `upgraded initiated flow`() { fun `upgraded initiated flow`() {
node2.registerFlowFactory(SendFlow::class, initiatedFlowVersion = 2) { UpgradedFlow(it) } 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) node1.services.startFlow(initiatingFlow)
mockNet.runNetwork() mockNet.runNetwork()
assertThat(receivedSessionMessages).startsWith( assertThat(receivedSessionMessages).startsWith(
node1 sent sessionInit(SendFlow::class, flowVersion = 1, payload = "Old initiating") to node2, node1 sent sessionInit(SendFlow::class, flowVersion = 1, payload = "Old initiating") to node2,
node2 sent sessionConfirm(flowVersion = 2) to node1 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 @Test
fun `unregistered flow`() { 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() mockNet.runNetwork()
assertThatExceptionOfType(UnexpectedFlowEndException::class.java) assertThatExceptionOfType(UnexpectedFlowEndException::class.java)
.isThrownBy { future.getOrThrow() } .isThrownBy { future.getOrThrow() }
@ -725,7 +718,7 @@ class FlowFrameworkTests {
@Test @Test
fun `single inlined sub-flow`() { fun `single inlined sub-flow`() {
node2.registerFlowFactory(SendAndReceiveFlow::class) { SingleInlinedSubFlow(it) } 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() mockNet.runNetwork()
assertThat(result.getOrThrow()).isEqualTo("HelloHello") assertThat(result.getOrThrow()).isEqualTo("HelloHello")
} }
@ -733,7 +726,7 @@ class FlowFrameworkTests {
@Test @Test
fun `double inlined sub-flow`() { fun `double inlined sub-flow`() {
node2.registerFlowFactory(SendAndReceiveFlow::class) { DoubleInlinedSubFlow(it) } 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() mockNet.runNetwork()
assertThat(result.getOrThrow()).isEqualTo("HelloHello") assertThat(result.getOrThrow()).isEqualTo("HelloHello")
} }
@ -788,7 +781,7 @@ class FlowFrameworkTests {
private fun StartedNode<*>.sendSessionMessage(message: SessionMessage, destination: StartedNode<*>) { private fun StartedNode<*>.sendSessionMessage(message: SessionMessage, destination: StartedNode<*>) {
services.networkService.apply { 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) 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.internal.StartedNode
import net.corda.node.services.network.NetworkMapService import net.corda.node.services.network.NetworkMapService
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand import net.corda.testing.dummyCommand
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
@ -54,7 +55,7 @@ class NotaryServiceTests {
val inputState = issueState(clientNode) val inputState = issueState(clientNode)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState) .addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey)) .addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
.setTimeWindow(Instant.now(), 30.seconds) .setTimeWindow(Instant.now(), 30.seconds)
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }
@ -70,7 +71,7 @@ class NotaryServiceTests {
val inputState = issueState(clientNode) val inputState = issueState(clientNode)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState) .addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey)) .addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }
@ -85,7 +86,7 @@ class NotaryServiceTests {
val inputState = issueState(clientNode) val inputState = issueState(clientNode)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState) .addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey)) .addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
.setTimeWindow(Instant.now().plusSeconds(3600), 30.seconds) .setTimeWindow(Instant.now().plusSeconds(3600), 30.seconds)
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }
@ -102,7 +103,7 @@ class NotaryServiceTests {
val inputState = issueState(clientNode) val inputState = issueState(clientNode)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState) .addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey)) .addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }
@ -122,14 +123,14 @@ class NotaryServiceTests {
val stx = run { val stx = run {
val tx = TransactionBuilder(notaryNode.info.notaryIdentity) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState) .addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey)) .addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }
val stx2 = run { val stx2 = run {
val tx = TransactionBuilder(notaryNode.info.notaryIdentity) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState) .addInputState(inputState)
.addInputState(issueState(clientNode)) .addInputState(issueState(clientNode))
.addCommand(dummyCommand(clientNode.services.legalIdentityKey)) .addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }
@ -154,7 +155,7 @@ class NotaryServiceTests {
} }
fun issueState(node: StartedNode<*>): StateAndRef<*> { 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 signedByNode = node.services.signInitialTransaction(tx)
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey) val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
node.services.recordTransactions(stx) 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.node.services.network.NetworkMapService
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.MEGA_CORP_KEY import net.corda.testing.MEGA_CORP_KEY
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand import net.corda.testing.dummyCommand
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
@ -56,7 +57,7 @@ class ValidatingNotaryServiceTests {
val inputState = issueInvalidState(clientNode, notaryNode.info.notaryIdentity) val inputState = issueInvalidState(clientNode, notaryNode.info.notaryIdentity)
val tx = TransactionBuilder(notaryNode.info.notaryIdentity) val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
.addInputState(inputState) .addInputState(inputState)
.addCommand(dummyCommand(clientNode.services.legalIdentityKey)) .addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
clientNode.services.signInitialTransaction(tx) clientNode.services.signInitialTransaction(tx)
} }
@ -97,7 +98,7 @@ class ValidatingNotaryServiceTests {
} }
fun issueState(node: StartedNode<*>): StateAndRef<*> { 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 signedByNode = node.services.signInitialTransaction(tx)
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey) val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
node.services.recordTransactions(stx) node.services.recordTransactions(stx)

View File

@ -445,7 +445,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
val megaCorpServices = MockServices(MEGA_CORP_KEY) val megaCorpServices = MockServices(MEGA_CORP_KEY)
database.transaction { database.transaction {
val freshKey = services.legalIdentityKey val freshKey = services.myInfo.chooseIdentity().owningKey
// Issue a txn to Send us some Money // Issue a txn to Send us some Money
val usefulBuilder = TransactionBuilder(null).apply { val usefulBuilder = TransactionBuilder(null).apply {
@ -477,11 +477,11 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
fun `is ownable state relevant`() { fun `is ownable state relevant`() {
val service = (services.vaultService as NodeVaultService) val service = (services.vaultService as NodeVaultService)
val amount = Amount(1000, Issued(BOC.ref(1), GBP)) 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)) val myKeys = services.keyManagementService.filterMyKeys(listOf(wellKnownCash.owner.owningKey))
assertTrue { service.isRelevant(wellKnownCash, myKeys.toSet()) } 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 anonymousCash = Cash.State(amount, anonymousIdentity.party)
val anonymousKeys = services.keyManagementService.filterMyKeys(listOf(anonymousCash.owner.owningKey)) val anonymousKeys = services.keyManagementService.filterMyKeys(listOf(anonymousCash.owner.owningKey))
assertTrue { service.isRelevant(anonymousCash, anonymousKeys.toSet()) } assertTrue { service.isRelevant(anonymousCash, anonymousKeys.toSet()) }
@ -501,14 +501,14 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
service.updates.subscribe(this) 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 thirdPartyIdentity = AnonymousParty(generateKeyPair().public)
val amount = Amount(1000, Issued(BOC.ref(1), GBP)) val amount = Amount(1000, Issued(BOC.ref(1), GBP))
// Issue then move some cash // Issue then move some cash
val issueTx = TransactionBuilder(services.myInfo.legalIdentity).apply { val issueTx = TransactionBuilder(services.myInfo.chooseIdentity()).apply {
Cash().generateIssue(this, Cash().generateIssue(this,
amount, anonymousIdentity.party, services.myInfo.legalIdentity) amount, anonymousIdentity.party, services.myInfo.chooseIdentity())
}.toWireTransaction() }.toWireTransaction()
val cashState = StateAndRef(issueTx.outputs.single(), StateRef(issueTx.id, 0)) 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) val expectedIssueUpdate = Vault.Update(emptySet(), setOf(cashState), null)
database.transaction { database.transaction {
val moveTx = TransactionBuilder(services.myInfo.legalIdentity).apply { val moveTx = TransactionBuilder(services.myInfo.chooseIdentity()).apply {
Cash.generateSpend(services, this, Amount(1000, GBP), thirdPartyIdentity) Cash.generateSpend(services, this, Amount(1000, GBP), thirdPartyIdentity)
}.toWireTransaction() }.toWireTransaction()
service.notify(moveTx) service.notify(moveTx)
@ -530,13 +530,13 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
@Test @Test
fun `correct updates are generated when changing notaries`() { fun `correct updates are generated when changing notaries`() {
val service = (services.vaultService as NodeVaultService) val service = (services.vaultService as NodeVaultService)
val notary = services.myInfo.legalIdentity val notary = services.myInfo.chooseIdentity()
val vaultSubscriber = TestSubscriber<Vault.Update<*>>().apply { val vaultSubscriber = TestSubscriber<Vault.Update<*>>().apply {
service.updates.subscribe(this) 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 thirdPartyIdentity = AnonymousParty(generateKeyPair().public)
val amount = Amount(1000, Issued(BOC.ref(1), GBP)) 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 { 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)
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) val dummyIssue = notaryServices.signInitialTransaction(dummyIssueBuilder)
@ -255,7 +255,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
database.transaction { // Issue a linear state database.transaction { // Issue a linear state
val dummyIssueBuilder = TransactionBuilder(notary = DUMMY_NOTARY) val dummyIssueBuilder = TransactionBuilder(notary = DUMMY_NOTARY)
.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 dummyIssuePtx = notaryServices.signInitialTransaction(dummyIssueBuilder) val dummyIssuePtx = notaryServices.signInitialTransaction(dummyIssueBuilder)
val dummyIssue = services.addSignature(dummyIssuePtx) val dummyIssue = services.addSignature(dummyIssuePtx)
@ -271,7 +271,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
val dummyMoveBuilder = TransactionBuilder(notary = DUMMY_NOTARY) val dummyMoveBuilder = TransactionBuilder(notary = DUMMY_NOTARY)
.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)
.addInputState(dummyIssue.tx.outRef<LinearState>(0)) .addInputState(dummyIssue.tx.outRef<LinearState>(0))
.addCommand(dummyCommand(notaryServices.legalIdentityKey)) .addCommand(dummyCommand(notaryServices.myInfo.chooseIdentity().owningKey))
val dummyMove = notaryServices.signInitialTransaction(dummyMoveBuilder) val dummyMove = notaryServices.signInitialTransaction(dummyMoveBuilder)
@ -347,7 +347,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
addOutputState(DummyDealContract.State(ref = "999", participants = listOf(freshIdentity)), DUMMY_DEAL_PROGRAM_ID) addOutputState(DummyDealContract.State(ref = "999", participants = listOf(freshIdentity)), DUMMY_DEAL_PROGRAM_ID)
addInputState(linearStates.first()) addInputState(linearStates.first())
addInputState(deals.first()) addInputState(deals.first())
addCommand(dummyCommand(notaryServices.legalIdentityKey)) addCommand(dummyCommand(notaryServices.myInfo.chooseIdentity().owningKey))
} }
val dummyMove = notaryServices.signInitialTransaction(dummyMoveBuilder) 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.core.utilities.getOrThrow
import net.corda.testing.DUMMY_BANK_B import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.driver.poll import net.corda.testing.driver.poll
import java.io.InputStream import java.io.InputStream
import java.net.HttpURLConnection 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 // Create a trivial transaction with an output that describes the attachment, and the attachment itself
val ptx = TransactionBuilder(notary) val ptx = TransactionBuilder(notary)
.addOutputState(AttachmentContract.State(hash), ATTACHMENT_PROGRAM_ID) .addOutputState(AttachmentContract.State(hash), ATTACHMENT_PROGRAM_ID)
.addCommand(AttachmentContract.Command, serviceHub.legalIdentityKey) .addCommand(AttachmentContract.Command, serviceHub.myInfo.chooseIdentity().owningKey)
.addAttachment(hash) .addAttachment(hash)
progressTracker.currentStep = SIGNING progressTracker.currentStep = SIGNING

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