mirror of
https://github.com/corda/corda.git
synced 2025-01-26 14:19:23 +00:00
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:
parent
d747f71fe5
commit
495e870b74
@ -94,13 +94,13 @@ class NodeMonitorModelTest : DriverBasedTest() {
|
||||
sequence(
|
||||
// TODO : Add test for remove when driver DSL support individual node shutdown.
|
||||
expect { output: NetworkMapCache.MapChange ->
|
||||
require(output.node.legalIdentity.name == ALICE.name) { "Expecting : ${ALICE.name}, Actual : ${output.node.legalIdentity.name}" }
|
||||
require(output.node.chooseIdentity().name == ALICE.name) { "Expecting : ${ALICE.name}, Actual : ${output.node.chooseIdentity().name}" }
|
||||
},
|
||||
expect { output: NetworkMapCache.MapChange ->
|
||||
require(output.node.legalIdentity.name == BOB.name) { "Expecting : ${BOB.name}, Actual : ${output.node.legalIdentity.name}" }
|
||||
require(output.node.chooseIdentity().name == BOB.name) { "Expecting : ${BOB.name}, Actual : ${output.node.chooseIdentity().name}" }
|
||||
},
|
||||
expect { output: NetworkMapCache.MapChange ->
|
||||
require(output.node.legalIdentity.name == CHARLIE.name) { "Expecting : ${CHARLIE.name}, Actual : ${output.node.legalIdentity.name}" }
|
||||
require(output.node.chooseIdentity().name == CHARLIE.name) { "Expecting : ${CHARLIE.name}, Actual : ${output.node.chooseIdentity().name}" }
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -134,7 +134,7 @@ class NodeMonitorModelTest : DriverBasedTest() {
|
||||
fun `cash issue and move`() {
|
||||
val anonymous = false
|
||||
val (_, issueIdentity) = rpc.startFlow(::CashIssueFlow, 100.DOLLARS, OpaqueBytes.of(1), notaryNode.notaryIdentity).returnValue.getOrThrow()
|
||||
val (_, paymentIdentity) = rpc.startFlow(::CashPaymentFlow, 100.DOLLARS, bobNode.legalIdentity).returnValue.getOrThrow()
|
||||
val (_, paymentIdentity) = rpc.startFlow(::CashPaymentFlow, 100.DOLLARS, bobNode.chooseIdentity()).returnValue.getOrThrow()
|
||||
|
||||
var issueSmId: StateMachineRunId? = null
|
||||
var moveSmId: StateMachineRunId? = null
|
||||
@ -167,7 +167,7 @@ class NodeMonitorModelTest : DriverBasedTest() {
|
||||
// MOVE
|
||||
expect { add: StateMachineUpdate.Added ->
|
||||
val initiator = add.stateMachineInfo.initiator
|
||||
require(initiator is FlowInitiator.Peer && initiator.party.name == aliceNode.legalIdentity.name)
|
||||
require(initiator is FlowInitiator.Peer && initiator.party.name == aliceNode.chooseIdentity().name)
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -180,7 +180,7 @@ class NodeMonitorModelTest : DriverBasedTest() {
|
||||
require(stx.tx.outputs.size == 1)
|
||||
val signaturePubKeys = stx.sigs.map { it.by }.toSet()
|
||||
// Only Alice signed
|
||||
val aliceKey = aliceNode.legalIdentity.owningKey
|
||||
val aliceKey = aliceNode.chooseIdentity().owningKey
|
||||
require(signaturePubKeys.size <= aliceKey.keys.size)
|
||||
require(aliceKey.isFulfilledBy(signaturePubKeys))
|
||||
issueTx = stx
|
||||
|
@ -38,7 +38,8 @@ class NetworkIdentityModel {
|
||||
|
||||
val parties: ObservableList<NodeInfo> = networkIdentities.filtered { !it.isCordaService() }
|
||||
val notaries: ObservableList<NodeInfo> = networkIdentities.filtered { it.advertisedServices.any { it.info.type.isNotary() } }
|
||||
val myIdentity = rpcProxy.map { it?.nodeIdentity() }
|
||||
val myNodeInfo = rpcProxy.map { it?.nodeInfo() } // TODO Used only for querying for advertised services, remove with services.
|
||||
val myIdentity = myNodeInfo.map { it?.legalIdentitiesAndCerts?.first()?.party }
|
||||
|
||||
private fun NodeInfo.isCordaService(): Boolean {
|
||||
// TODO: better way to identify Corda service?
|
||||
@ -46,4 +47,11 @@ class NetworkIdentityModel {
|
||||
}
|
||||
|
||||
fun partyFromPublicKey(publicKey: PublicKey): ObservableValue<NodeInfo?> = identityCache[publicKey]
|
||||
//TODO rebase fix
|
||||
// // TODO: Use Identity Service in service hub instead?
|
||||
// fun lookup(publicKey: PublicKey): ObservableValue<PartyAndCertificate?> {
|
||||
// val party = parties.flatMap { it.legalIdentitiesAndCerts }.firstOrNull { publicKey in it.owningKey.keys } ?:
|
||||
// notaries.flatMap { it.legalIdentitiesAndCerts }.firstOrNull { it.owningKey.keys.any { it == publicKey }}
|
||||
// return ReadOnlyObjectWrapper(party)
|
||||
// }
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import net.corda.node.internal.Node;
|
||||
import net.corda.node.internal.StartedNode;
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService;
|
||||
import net.corda.nodeapi.User;
|
||||
import net.corda.testing.CoreTestUtils;
|
||||
import net.corda.testing.node.NodeBasedTest;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@ -74,7 +75,7 @@ public class CordaRPCJavaClientTest extends NodeBasedTest {
|
||||
|
||||
FlowHandle<AbstractCashFlow.Result> flowHandle = rpcProxy.startFlowDynamic(CashIssueFlow.class,
|
||||
DOLLARS(123), OpaqueBytes.of("1".getBytes()),
|
||||
node.getInfo().getLegalIdentity());
|
||||
CoreTestUtils.chooseIdentity(node.getInfo()));
|
||||
System.out.println("Started issuing cash, waiting on result");
|
||||
flowHandle.getReturnValue().get();
|
||||
|
||||
|
@ -20,6 +20,7 @@ import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.NodeBasedTest
|
||||
import org.apache.activemq.artemis.api.core.ActiveMQSecurityException
|
||||
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||
@ -81,7 +82,7 @@ class CordaRPCClientTest : NodeBasedTest() {
|
||||
println("Creating proxy")
|
||||
println("Starting flow")
|
||||
val flowHandle = connection!!.proxy.startTrackedFlow(::CashIssueFlow,
|
||||
20.DOLLARS, OpaqueBytes.of(0), node.info.legalIdentity
|
||||
20.DOLLARS, OpaqueBytes.of(0), node.info.chooseIdentity()
|
||||
)
|
||||
println("Started flow, waiting on result")
|
||||
flowHandle.progress.subscribe {
|
||||
@ -93,7 +94,7 @@ class CordaRPCClientTest : NodeBasedTest() {
|
||||
@Test
|
||||
fun `sub-type of FlowException thrown by flow`() {
|
||||
login(rpcUser.username, rpcUser.password)
|
||||
val handle = connection!!.proxy.startFlow(::CashPaymentFlow, 100.DOLLARS, node.info.legalIdentity)
|
||||
val handle = connection!!.proxy.startFlow(::CashPaymentFlow, 100.DOLLARS, node.info.chooseIdentity())
|
||||
assertThatExceptionOfType(CashException::class.java).isThrownBy {
|
||||
handle.returnValue.getOrThrow()
|
||||
}
|
||||
@ -102,7 +103,7 @@ class CordaRPCClientTest : NodeBasedTest() {
|
||||
@Test
|
||||
fun `check basic flow has no progress`() {
|
||||
login(rpcUser.username, rpcUser.password)
|
||||
connection!!.proxy.startFlow(::CashPaymentFlow, 100.DOLLARS, node.info.legalIdentity).use {
|
||||
connection!!.proxy.startFlow(::CashPaymentFlow, 100.DOLLARS, node.info.chooseIdentity()).use {
|
||||
assertFalse(it is FlowProgressHandle<*>)
|
||||
assertTrue(it is FlowHandle<*>)
|
||||
}
|
||||
@ -116,7 +117,7 @@ class CordaRPCClientTest : NodeBasedTest() {
|
||||
assertTrue(startCash.isEmpty(), "Should not start with any cash")
|
||||
|
||||
val flowHandle = proxy.startFlow(::CashIssueFlow,
|
||||
123.DOLLARS, OpaqueBytes.of(0), node.info.legalIdentity
|
||||
123.DOLLARS, OpaqueBytes.of(0), node.info.chooseIdentity()
|
||||
)
|
||||
println("Started issuing cash, waiting on result")
|
||||
flowHandle.returnValue.get()
|
||||
@ -141,7 +142,7 @@ class CordaRPCClientTest : NodeBasedTest() {
|
||||
countShellFlows++
|
||||
}
|
||||
}
|
||||
val nodeIdentity = node.info.legalIdentity
|
||||
val nodeIdentity = node.info.chooseIdentity()
|
||||
node.services.startFlow(CashIssueFlow(2000.DOLLARS, OpaqueBytes.of(0), nodeIdentity), FlowInitiator.Shell).resultFuture.getOrThrow()
|
||||
proxy.startFlow(::CashIssueFlow,
|
||||
123.DOLLARS,
|
||||
|
@ -3,6 +3,7 @@ package net.corda.java.rpc;
|
||||
import net.corda.client.rpc.CordaRPCConnection;
|
||||
import net.corda.core.contracts.Amount;
|
||||
import net.corda.core.identity.CordaX500Name;
|
||||
import net.corda.core.identity.Party;
|
||||
import net.corda.core.messaging.CordaRPCOps;
|
||||
import net.corda.core.messaging.FlowHandle;
|
||||
import net.corda.core.node.NodeInfo;
|
||||
@ -41,6 +42,7 @@ public class StandaloneCordaRPCJavaClientTest {
|
||||
private CordaRPCOps rpcProxy;
|
||||
private CordaRPCConnection connection;
|
||||
private NodeInfo notaryNode;
|
||||
private Party notaryNodeIdentity;
|
||||
|
||||
private NodeConfig notaryConfig = new NodeConfig(
|
||||
new CordaX500Name("Notary Service", "Zurich", "CH"),
|
||||
@ -60,6 +62,7 @@ public class StandaloneCordaRPCJavaClientTest {
|
||||
connection = notary.connect();
|
||||
rpcProxy = connection.getProxy();
|
||||
notaryNode = fetchNotaryIdentity();
|
||||
notaryNodeIdentity = rpcProxy.nodeInfo().getLegalIdentities().get(0);
|
||||
}
|
||||
|
||||
@After
|
||||
@ -106,7 +109,7 @@ public class StandaloneCordaRPCJavaClientTest {
|
||||
|
||||
FlowHandle<AbstractCashFlow.Result> flowHandle = rpcProxy.startFlowDynamic(CashIssueFlow.class,
|
||||
dollars123, OpaqueBytes.of("1".getBytes()),
|
||||
notaryNode.getLegalIdentity());
|
||||
notaryNodeIdentity);
|
||||
System.out.println("Started issuing cash, waiting on result");
|
||||
flowHandle.getReturnValue().get();
|
||||
|
||||
|
@ -5,6 +5,7 @@ import com.google.common.hash.HashingInputStream
|
||||
import net.corda.client.rpc.CordaRPCConnection
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.messaging.*
|
||||
import net.corda.core.node.NodeInfo
|
||||
@ -56,6 +57,7 @@ class StandaloneCordaRPClientTest {
|
||||
private lateinit var rpcProxy: CordaRPCOps
|
||||
private lateinit var connection: CordaRPCConnection
|
||||
private lateinit var notaryNode: NodeInfo
|
||||
private lateinit var notaryNodeIdentity: Party
|
||||
|
||||
private val notaryConfig = NodeConfig(
|
||||
legalName = CordaX500Name(organisation = "Notary Service", locality = "Zurich", country = "CH"),
|
||||
@ -74,6 +76,7 @@ class StandaloneCordaRPClientTest {
|
||||
connection = notary.connect()
|
||||
rpcProxy = connection.proxy
|
||||
notaryNode = fetchNotaryIdentity()
|
||||
notaryNodeIdentity = rpcProxy.nodeInfo().legalIdentitiesAndCerts.first().party
|
||||
}
|
||||
|
||||
@After
|
||||
@ -110,7 +113,7 @@ class StandaloneCordaRPClientTest {
|
||||
|
||||
@Test
|
||||
fun `test starting flow`() {
|
||||
rpcProxy.startFlow(::CashIssueFlow, 127.POUNDS, OpaqueBytes.of(0), notaryNode.notaryIdentity)
|
||||
rpcProxy.startFlow(::CashIssueFlow, 127.POUNDS, OpaqueBytes.of(0), notaryNodeIdentity)
|
||||
.returnValue.getOrThrow(timeout)
|
||||
}
|
||||
|
||||
@ -118,7 +121,7 @@ class StandaloneCordaRPClientTest {
|
||||
fun `test starting tracked flow`() {
|
||||
var trackCount = 0
|
||||
val handle = rpcProxy.startTrackedFlow(
|
||||
::CashIssueFlow, 429.DOLLARS, OpaqueBytes.of(0), notaryNode.notaryIdentity
|
||||
::CashIssueFlow, 429.DOLLARS, OpaqueBytes.of(0), notaryNodeIdentity
|
||||
)
|
||||
val updateLatch = CountDownLatch(1)
|
||||
handle.progress.subscribe { msg ->
|
||||
@ -133,7 +136,7 @@ class StandaloneCordaRPClientTest {
|
||||
|
||||
@Test
|
||||
fun `test network map`() {
|
||||
assertEquals(notaryConfig.legalName, notaryNode.legalIdentity.name)
|
||||
assertEquals(notaryConfig.legalName, notaryNodeIdentity.name)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -152,7 +155,7 @@ class StandaloneCordaRPClientTest {
|
||||
}
|
||||
|
||||
// Now issue some cash
|
||||
rpcProxy.startFlow(::CashIssueFlow, 513.SWISS_FRANCS, OpaqueBytes.of(0), notaryNode.notaryIdentity)
|
||||
rpcProxy.startFlow(::CashIssueFlow, 513.SWISS_FRANCS, OpaqueBytes.of(0), notaryNodeIdentity)
|
||||
.returnValue.getOrThrow(timeout)
|
||||
updateLatch.await()
|
||||
assertEquals(1, updateCount.get())
|
||||
@ -170,7 +173,7 @@ class StandaloneCordaRPClientTest {
|
||||
}
|
||||
|
||||
// Now issue some cash
|
||||
rpcProxy.startFlow(::CashIssueFlow, 629.POUNDS, OpaqueBytes.of(0), notaryNode.notaryIdentity)
|
||||
rpcProxy.startFlow(::CashIssueFlow, 629.POUNDS, OpaqueBytes.of(0), notaryNodeIdentity)
|
||||
.returnValue.getOrThrow(timeout)
|
||||
updateLatch.await()
|
||||
|
||||
@ -184,7 +187,7 @@ class StandaloneCordaRPClientTest {
|
||||
@Test
|
||||
fun `test vault query by`() {
|
||||
// Now issue some cash
|
||||
rpcProxy.startFlow(::CashIssueFlow, 629.POUNDS, OpaqueBytes.of(0), notaryNode.notaryIdentity)
|
||||
rpcProxy.startFlow(::CashIssueFlow, 629.POUNDS, OpaqueBytes.of(0), notaryNodeIdentity)
|
||||
.returnValue.getOrThrow(timeout)
|
||||
|
||||
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)
|
||||
@ -195,7 +198,7 @@ class StandaloneCordaRPClientTest {
|
||||
assertEquals(1, queryResults.totalStatesAvailable)
|
||||
assertEquals(queryResults.states.first().state.data.amount.quantity, 629.POUNDS.quantity)
|
||||
|
||||
rpcProxy.startFlow(::CashPaymentFlow, 100.POUNDS, notaryNode.legalIdentity).returnValue.getOrThrow()
|
||||
rpcProxy.startFlow(::CashPaymentFlow, 100.POUNDS, notaryNodeIdentity).returnValue.getOrThrow()
|
||||
|
||||
val moreResults = rpcProxy.vaultQueryBy<Cash.State>(criteria, paging, sorting)
|
||||
assertEquals(3, moreResults.totalStatesAvailable) // 629 - 100 + 100
|
||||
@ -213,7 +216,7 @@ class StandaloneCordaRPClientTest {
|
||||
println(startCash)
|
||||
assertTrue(startCash.isEmpty(), "Should not start with any cash")
|
||||
|
||||
val flowHandle = rpcProxy.startFlow(::CashIssueFlow, 629.DOLLARS, OpaqueBytes.of(0), notaryNode.legalIdentity)
|
||||
val flowHandle = rpcProxy.startFlow(::CashIssueFlow, 629.DOLLARS, OpaqueBytes.of(0), notaryNodeIdentity)
|
||||
println("Started issuing cash, waiting on result")
|
||||
flowHandle.returnValue.get()
|
||||
|
||||
|
@ -96,10 +96,10 @@ abstract class AbstractStateReplacementFlow {
|
||||
|
||||
@Suspendable
|
||||
private fun collectSignatures(participants: Iterable<PublicKey>, stx: SignedTransaction): List<TransactionSignature> {
|
||||
// In identity service we record all identities we know about from network map.
|
||||
val parties = participants.map {
|
||||
val participantNode = serviceHub.networkMapCache.getNodeByLegalIdentityKey(it) ?:
|
||||
serviceHub.identityService.partyFromKey(it) ?:
|
||||
throw IllegalStateException("Participant $it to state $originalState not found on the network")
|
||||
participantNode.legalIdentity
|
||||
}
|
||||
|
||||
val participantSignatures = parties.map { getParticipantSignature(it, stx) }
|
||||
@ -193,7 +193,8 @@ abstract class AbstractStateReplacementFlow {
|
||||
|
||||
private fun checkMySignatureRequired(stx: SignedTransaction) {
|
||||
// TODO: use keys from the keyManagementService instead
|
||||
val myKey = serviceHub.myInfo.legalIdentity.owningKey
|
||||
// TODO Check the set of multiple identities?
|
||||
val myKey = ourIdentity.owningKey
|
||||
|
||||
val requiredKeys = if (stx.isNotaryChangeTransaction()) {
|
||||
stx.resolveNotaryChangeTransaction(serviceHub).requiredSigningKeys
|
||||
|
@ -20,7 +20,7 @@ class BroadcastTransactionFlow(val notarisedTransaction: SignedTransaction,
|
||||
@Suspendable
|
||||
override fun call() {
|
||||
// TODO: Messaging layer should handle this broadcast for us
|
||||
participants.filter { it != serviceHub.myInfo.legalIdentity }.forEach { participant ->
|
||||
participants.filter { it !in serviceHub.myInfo.legalIdentities }.forEach { participant ->
|
||||
// SendTransactionFlow allows otherParty to access our data to resolve the transaction.
|
||||
subFlow(SendTransactionFlow(participant, notarisedTransaction))
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ class CollectSignaturesFlow @JvmOverloads constructor (val partiallySignedTx: Si
|
||||
@Suspendable override fun call(): SignedTransaction {
|
||||
// Check the signatures which have already been provided and that the transaction is valid.
|
||||
// Usually just the Initiator and possibly an oracle would have signed at this point.
|
||||
val myKeys: Iterable<PublicKey> = myOptionalKeys ?: listOf(serviceHub.myInfo.legalIdentity.owningKey)
|
||||
val myKeys: Iterable<PublicKey> = myOptionalKeys ?: listOf(ourIdentity.owningKey)
|
||||
val signed = partiallySignedTx.sigs.map { it.by }
|
||||
val notSigned = partiallySignedTx.tx.requiredSigningKeys - signed
|
||||
|
||||
@ -112,7 +112,7 @@ class CollectSignaturesFlow @JvmOverloads constructor (val partiallySignedTx: Si
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the [Party] object for each [PublicKey] using the [ServiceHub.networkMapCache].
|
||||
* Lookup the [Party] object for each [PublicKey] using the [ServiceHub.identityService].
|
||||
*
|
||||
* @return a pair of the well known identity to contact for a signature, and the public key that party should sign
|
||||
* with (this may belong to a confidential identity).
|
||||
|
@ -53,8 +53,6 @@ open class FinalityFlow(val transactions: Iterable<SignedTransaction>,
|
||||
fun tracker() = ProgressTracker(NOTARISING, BROADCASTING)
|
||||
}
|
||||
|
||||
open protected val ourIdentity: Party get() = serviceHub.myInfo.legalIdentity
|
||||
|
||||
@Suspendable
|
||||
@Throws(NotaryException::class)
|
||||
override fun call(): List<SignedTransaction> {
|
||||
@ -70,7 +68,7 @@ open class FinalityFlow(val transactions: Iterable<SignedTransaction>,
|
||||
// Each transaction has its own set of recipients, but extra recipients get them all.
|
||||
progressTracker.currentStep = BROADCASTING
|
||||
for ((stx, parties) in notarisedTxns) {
|
||||
val participants = (parties + extraRecipients).filter { it != ourIdentity }.toSet()
|
||||
val participants = (parties + extraRecipients).filter { it != ourIdentity.party }.toSet()
|
||||
if (participants.isNotEmpty()) {
|
||||
broadcastTransaction(stx, participants.toNonEmptySet())
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package net.corda.core.flows
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.internal.FlowStateMachine
|
||||
import net.corda.core.internal.abbreviate
|
||||
import net.corda.core.messaging.DataFeed
|
||||
@ -56,6 +57,12 @@ abstract class FlowLogic<out T> {
|
||||
@Suspendable
|
||||
fun initiateFlow(party: Party): FlowSession = stateMachine.initiateFlow(party, flowUsedForSessions)
|
||||
|
||||
/**
|
||||
* Specifies our identity in the flow. With node's multiple identities we can choose which one to use for communication.
|
||||
* Defaults to the first one from [NodeInfo.legalIdentitiesAndCerts].
|
||||
*/
|
||||
val ourIdentity: PartyAndCertificate get() = stateMachine.ourIdentity
|
||||
|
||||
/**
|
||||
* Returns a [FlowInfo] object describing the flow [otherParty] is using. With [FlowInfo.flowVersion] it
|
||||
* provides the necessary information needed for the evolution of flows and enabling backwards compatibility.
|
||||
|
@ -39,7 +39,7 @@ object IdentitySyncFlow {
|
||||
val identities: Set<AbstractParty> = states.flatMap { it.participants }.toSet()
|
||||
// Filter participants down to the set of those not in the network map (are not well known)
|
||||
val confidentialIdentities = identities
|
||||
.filter { serviceHub.networkMapCache.getNodeByLegalIdentityKey(it.owningKey) == null }
|
||||
.filter { serviceHub.networkMapCache.getNodesByLegalIdentityKey(it.owningKey).isEmpty() }
|
||||
.toList()
|
||||
val identityCertificates: Map<AbstractParty, PartyAndCertificate?> = identities
|
||||
.map { Pair(it, serviceHub.identityService.certificateFromKey(it.owningKey)) }.toMap()
|
||||
|
@ -36,17 +36,17 @@ class SwapIdentitiesFlow(val otherSide: Party,
|
||||
@Suspendable
|
||||
override fun call(): LinkedHashMap<Party, AnonymousParty> {
|
||||
progressTracker.currentStep = AWAITING_KEY
|
||||
val legalIdentityAnonymous = serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.legalIdentityAndCert, revocationEnabled)
|
||||
val legalIdentityAnonymous = serviceHub.keyManagementService.freshKeyAndCert(ourIdentity, revocationEnabled)
|
||||
|
||||
// Special case that if we're both parties, a single identity is generated
|
||||
val identities = LinkedHashMap<Party, AnonymousParty>()
|
||||
if (otherSide == serviceHub.myInfo.legalIdentity) {
|
||||
if (otherSide in serviceHub.myInfo.legalIdentities) {
|
||||
identities.put(otherSide, legalIdentityAnonymous.party.anonymise())
|
||||
} else {
|
||||
val anonymousOtherSide = sendAndReceive<PartyAndCertificate>(otherSide, legalIdentityAnonymous).unwrap { confidentialIdentity ->
|
||||
validateAndRegisterIdentity(serviceHub.identityService, otherSide, confidentialIdentity)
|
||||
}
|
||||
identities.put(serviceHub.myInfo.legalIdentity, legalIdentityAnonymous.party.anonymise())
|
||||
identities.put(ourIdentity.party, legalIdentityAnonymous.party.anonymise())
|
||||
identities.put(otherSide, anonymousOtherSide.party.anonymise())
|
||||
}
|
||||
return identities
|
||||
|
@ -5,6 +5,7 @@ import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.UntrustworthyData
|
||||
@ -49,4 +50,5 @@ interface FlowStateMachine<R> {
|
||||
val id: StateMachineRunId
|
||||
val resultFuture: CordaFuture<R>
|
||||
val flowInitiator: FlowInitiator
|
||||
val ourIdentity: PartyAndCertificate
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ interface CordaRPCOps : RPCOps {
|
||||
* Returns the RPC protocol version, which is the same the node's Platform Version. Exists since version 1 so guaranteed
|
||||
* to be present.
|
||||
*/
|
||||
override val protocolVersion: Int get() = nodeIdentity().platformVersion
|
||||
override val protocolVersion: Int get() = nodeInfo().platformVersion
|
||||
|
||||
/**
|
||||
* Returns a list of currently in-progress state machine infos.
|
||||
@ -208,9 +208,9 @@ interface CordaRPCOps : RPCOps {
|
||||
fun <T> startTrackedFlowDynamic(logicType: Class<out FlowLogic<T>>, vararg args: Any?): FlowProgressHandle<T>
|
||||
|
||||
/**
|
||||
* Returns Node's identity, assuming this will not change while the node is running.
|
||||
* Returns Node's NodeInfo, assuming this will not change while the node is running.
|
||||
*/
|
||||
fun nodeIdentity(): NodeInfo
|
||||
fun nodeInfo(): NodeInfo
|
||||
|
||||
/*
|
||||
* Add note(s) to an existing Vault transaction
|
||||
|
@ -18,22 +18,20 @@ data class ServiceEntry(val info: ServiceInfo, val identity: PartyAndCertificate
|
||||
* Info about a network node that acts on behalf of some form of contract party.
|
||||
*/
|
||||
// TODO We currently don't support multi-IP/multi-identity nodes, we only left slots in the data structures.
|
||||
// Note that order of `legalIdentitiesAndCerts` is now important. We still treat the first identity as a special one.
|
||||
// It will change after introducing proper multi-identity management.
|
||||
@CordaSerializable
|
||||
data class NodeInfo(val addresses: List<NetworkHostAndPort>,
|
||||
// TODO After removing of services these two fields will be merged together and made NonEmptySet.
|
||||
val legalIdentityAndCert: PartyAndCertificate,
|
||||
val legalIdentitiesAndCerts: Set<PartyAndCertificate>,
|
||||
val legalIdentitiesAndCerts: List<PartyAndCertificate>,
|
||||
val platformVersion: Int,
|
||||
val advertisedServices: List<ServiceEntry> = emptyList(),
|
||||
val serial: Long
|
||||
) {
|
||||
init {
|
||||
require(advertisedServices.none { it.identity == legalIdentityAndCert }) {
|
||||
"Service identities must be different from node legal identity"
|
||||
}
|
||||
require(legalIdentitiesAndCerts.isNotEmpty()) { "Node should have at least one legal identity" }
|
||||
}
|
||||
|
||||
val legalIdentity: Party get() = legalIdentityAndCert.party
|
||||
// TODO This part will be removed with services removal.
|
||||
val notaryIdentity: Party get() = advertisedServices.single { it.info.type.isNotary() }.identity.party
|
||||
fun serviceIdentities(type: ServiceType): List<Party> {
|
||||
return advertisedServices.mapNotNull { if (it.info.type.isSubTypeOf(type)) it.identity.party else null }
|
||||
@ -43,7 +41,9 @@ data class NodeInfo(val addresses: List<NetworkHostAndPort>,
|
||||
* Uses node's owner X500 name to infer the node's location. Used in Explorer in map view.
|
||||
*/
|
||||
fun getWorldMapLocation(): WorldMapLocation? {
|
||||
val nodeOwnerLocation = legalIdentity.name.locality
|
||||
val nodeOwnerLocation = legalIdentitiesAndCerts.first().name.locality
|
||||
return nodeOwnerLocation.let { CityDatabase[it] }
|
||||
}
|
||||
val legalIdentities: List<Party>
|
||||
get() = legalIdentitiesAndCerts.map { it.party }
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.crypto.SignableData
|
||||
import net.corda.core.crypto.SignatureMetadata
|
||||
import net.corda.core.crypto.TransactionSignature
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.node.services.*
|
||||
import net.corda.core.serialization.SerializeAsToken
|
||||
import net.corda.core.transactions.FilteredTransaction
|
||||
@ -129,16 +131,7 @@ interface ServiceHub : ServicesForResolution {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper property to shorten code for fetching the the [PublicKey] portion of the
|
||||
* Node's primary signing identity.
|
||||
* Typical use is during signing in flows and for unit test signing.
|
||||
* When this [PublicKey] is passed into the signing methods below, or on the KeyManagementService
|
||||
* the matching [java.security.PrivateKey] will be looked up internally and used to sign.
|
||||
* If the key is actually a CompositeKey, the first leaf key hosted on this node
|
||||
* will be used to create the signature.
|
||||
*/
|
||||
val legalIdentityKey: PublicKey get() = this.myInfo.legalIdentity.owningKey
|
||||
private val legalIdentityKey: PublicKey get() = this.myInfo.legalIdentitiesAndCerts.first().owningKey
|
||||
|
||||
/**
|
||||
* Helper property to shorten code for fetching the the [PublicKey] portion of the
|
||||
@ -288,4 +281,4 @@ interface ServiceHub : ServicesForResolution {
|
||||
* @return A new [Connection]
|
||||
*/
|
||||
fun jdbcSession(): Connection
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.randomOrNull
|
||||
import net.corda.core.messaging.DataFeed
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.ServiceEntry
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import rx.Observable
|
||||
@ -58,6 +59,14 @@ interface NetworkMapCache {
|
||||
return partyNodes.filter { it.advertisedServices.any { it.info.type.isSubTypeOf(serviceType) } }
|
||||
}
|
||||
|
||||
// TODO It will be removed with services + part of these functions will get merged into database backed NetworkMapCache
|
||||
fun getPeersWithService(serviceType: ServiceType): List<ServiceEntry> {
|
||||
return partyNodes.fold(ArrayList<ServiceEntry>()) {
|
||||
acc, elem -> acc.addAll(elem.advertisedServices.filter { it.info.type.isSubTypeOf(serviceType)})
|
||||
acc
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a recommended node that advertises a service, and is suitable for the specified contract and parties.
|
||||
* Implementations might understand, for example, the correct regulator to use for specific contracts/parties,
|
||||
@ -82,14 +91,17 @@ interface NetworkMapCache {
|
||||
/** Look up the node info for a host and port. */
|
||||
fun getNodeByAddress(address: NetworkHostAndPort): NodeInfo?
|
||||
|
||||
fun getPeerByLegalName(principal: CordaX500Name): Party? = getNodeByLegalName(principal)?.let {
|
||||
it.legalIdentitiesAndCerts.singleOrNull { it.name == principal }?.party
|
||||
}
|
||||
|
||||
/**
|
||||
* In general, nodes can advertise multiple identities: a legal identity, and separate identities for each of
|
||||
* the services it provides. In case of a distributed service – run by multiple nodes – each participant advertises
|
||||
* the identity of the *whole group*.
|
||||
*/
|
||||
|
||||
/** Look up the node info for a specific peer key. */
|
||||
fun getNodeByLegalIdentityKey(identityKey: PublicKey): NodeInfo?
|
||||
/** Look up the node infos for a specific peer key. */
|
||||
fun getNodesByLegalIdentityKey(identityKey: PublicKey): List<NodeInfo>
|
||||
|
||||
/** Look up all nodes advertising the service owned by [publicKey] */
|
||||
fun getNodesByAdvertisedServiceIdentityKey(publicKey: PublicKey): List<NodeInfo> {
|
||||
|
@ -1,21 +1,13 @@
|
||||
package net.corda.core.node.services
|
||||
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.ServiceEntry
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
|
||||
/**
|
||||
* Holds information about a [Party], which may refer to either a specific node or a service.
|
||||
*/
|
||||
sealed class PartyInfo {
|
||||
abstract val party: PartyAndCertificate
|
||||
|
||||
data class Node(val node: NodeInfo) : PartyInfo() {
|
||||
override val party get() = node.legalIdentityAndCert
|
||||
}
|
||||
|
||||
data class Service(val service: ServiceEntry) : PartyInfo() {
|
||||
override val party get() = service.identity
|
||||
}
|
||||
}
|
||||
abstract val party: Party
|
||||
data class SingleNode(override val party: Party, val addresses: List<NetworkHostAndPort>): PartyInfo()
|
||||
data class DistributedNode(override val party: Party): PartyInfo()
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ object NodeInfoSchemaV1 : MappedSchema(
|
||||
@JoinTable(name = "link_nodeinfo_party",
|
||||
joinColumns = arrayOf(JoinColumn(name="node_info_id")),
|
||||
inverseJoinColumns = arrayOf(JoinColumn(name="party_name")))
|
||||
val legalIdentitiesAndCerts: Set<DBPartyAndCertificate>,
|
||||
val legalIdentitiesAndCerts: List<DBPartyAndCertificate>,
|
||||
|
||||
@Column(name = "platform_version")
|
||||
val platformVersion: Int,
|
||||
@ -54,8 +54,7 @@ object NodeInfoSchemaV1 : MappedSchema(
|
||||
fun toNodeInfo(): NodeInfo {
|
||||
return NodeInfo(
|
||||
this.addresses.map { it.toHostAndPort() },
|
||||
this.legalIdentitiesAndCerts.filter { it.isMain }.single().toLegalIdentityAndCert(), // TODO Workaround, it will be changed after PR with services removal.
|
||||
this.legalIdentitiesAndCerts.filter { !it.isMain }.map { it.toLegalIdentityAndCert() }.toSet(),
|
||||
(this.legalIdentitiesAndCerts.filter { it.isMain } + this.legalIdentitiesAndCerts.filter { !it.isMain }).map { it.toLegalIdentityAndCert() },
|
||||
this.platformVersion,
|
||||
this.advertisedServices.map {
|
||||
it.serviceEntry?.deserialize<ServiceEntry>() ?: throw IllegalStateException("Service entry shouldn't be null")
|
||||
|
@ -4,6 +4,7 @@ import co.paralleluniverse.fibers.Suspendable;
|
||||
import com.google.common.primitives.Primitives;
|
||||
import net.corda.core.identity.Party;
|
||||
import net.corda.node.internal.StartedNode;
|
||||
import net.corda.testing.CoreTestUtils;
|
||||
import net.corda.testing.node.MockNetwork;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@ -39,7 +40,7 @@ public class FlowsInJavaTest {
|
||||
@Test
|
||||
public void suspendableActionInsideUnwrap() throws Exception {
|
||||
node2.getInternals().registerInitiatedFlow(SendHelloAndThenReceive.class);
|
||||
Future<String> result = node1.getServices().startFlow(new SendInUnwrapFlow(node2.getInfo().getLegalIdentity())).getResultFuture();
|
||||
Future<String> result = node1.getServices().startFlow(new SendInUnwrapFlow(CoreTestUtils.chooseIdentity(node2.getInfo()))).getResultFuture();
|
||||
mockNet.runNetwork();
|
||||
assertThat(result.get()).isEqualTo("Hello");
|
||||
}
|
||||
@ -54,7 +55,7 @@ public class FlowsInJavaTest {
|
||||
}
|
||||
|
||||
private void primitiveReceiveTypeTest(Class<?> receiveType) throws InterruptedException {
|
||||
PrimitiveReceiveFlow flow = new PrimitiveReceiveFlow(node2.getInfo().getLegalIdentity(), receiveType);
|
||||
PrimitiveReceiveFlow flow = new PrimitiveReceiveFlow(CoreTestUtils.chooseIdentity(node2.getInfo()), receiveType);
|
||||
Future<?> result = node1.getServices().startFlow(flow).getResultFuture();
|
||||
mockNet.runNetwork();
|
||||
try {
|
||||
|
@ -7,6 +7,7 @@ import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.TestDependencyInjectionBase
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.node.MockServices
|
||||
@ -68,8 +69,8 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
tx.addInputState(makeDummyStateAndRef(i.toString()))
|
||||
tx.addOutputState(makeDummyState(i), DUMMY_PROGRAM_ID)
|
||||
tx.addOutputState(makeDummyState(i.toString()), DUMMY_PROGRAM_ID)
|
||||
tx.addCommand(Commands.Cmd1(i), listOf(services.myInfo.legalIdentity.owningKey))
|
||||
tx.addCommand(Commands.Cmd2(i), listOf(services.myInfo.legalIdentity.owningKey))
|
||||
tx.addCommand(Commands.Cmd1(i), listOf(services.myInfo.chooseIdentity().owningKey))
|
||||
tx.addCommand(Commands.Cmd2(i), listOf(services.myInfo.chooseIdentity().owningKey))
|
||||
}
|
||||
return tx.toLedgerTransaction(services)
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.persistence.NodeAttachmentService
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.node.utilities.DatabaseTransactionManager
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@ -72,7 +73,7 @@ class AttachmentTests {
|
||||
|
||||
// Get node one to run a flow to fetch it and insert it.
|
||||
mockNet.runNetwork()
|
||||
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.legalIdentity)
|
||||
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.chooseIdentity())
|
||||
mockNet.runNetwork()
|
||||
assertEquals(0, f1.resultFuture.getOrThrow().fromDisk.size)
|
||||
|
||||
@ -86,7 +87,7 @@ class AttachmentTests {
|
||||
// Shut down node zero and ensure node one can still resolve the attachment.
|
||||
n0.dispose()
|
||||
|
||||
val response: FetchDataFlow.Result<Attachment> = n1.startAttachmentFlow(setOf(id), n0.info.legalIdentity).resultFuture.getOrThrow()
|
||||
val response: FetchDataFlow.Result<Attachment> = n1.startAttachmentFlow(setOf(id), n0.info.chooseIdentity()).resultFuture.getOrThrow()
|
||||
assertEquals(attachment, response.fromDisk[0])
|
||||
}
|
||||
|
||||
@ -106,7 +107,7 @@ class AttachmentTests {
|
||||
// Get node one to fetch a non-existent attachment.
|
||||
val hash = SecureHash.randomSHA256()
|
||||
mockNet.runNetwork()
|
||||
val f1 = n1.startAttachmentFlow(setOf(hash), n0.info.legalIdentity)
|
||||
val f1 = n1.startAttachmentFlow(setOf(hash), n0.info.chooseIdentity())
|
||||
mockNet.runNetwork()
|
||||
val e = assertFailsWith<FetchDataFlow.HashNotFound> { f1.resultFuture.getOrThrow() }
|
||||
assertEquals(hash, e.requested)
|
||||
@ -151,7 +152,7 @@ class AttachmentTests {
|
||||
|
||||
// Get n1 to fetch the attachment. Should receive corrupted bytes.
|
||||
mockNet.runNetwork()
|
||||
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.legalIdentity)
|
||||
val f1 = n1.startAttachmentFlow(setOf(id), n0.info.chooseIdentity())
|
||||
mockNet.runNetwork()
|
||||
assertFailsWith<FetchDataFlow.DownloadedVsRequestedDataMismatch> { f1.resultFuture.getOrThrow() }
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.MINI_CORP_KEY
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.chooseIdentityAndCert
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.After
|
||||
@ -54,7 +56,7 @@ class CollectSignaturesFlowTests {
|
||||
}
|
||||
|
||||
// With this flow, the initiators sends an "offer" to the responder, who then initiates the collect signatures flow.
|
||||
// This flow is a more simplifed version of the "TwoPartyTrade" flow and is a useful example of how both the
|
||||
// This flow is a more simplified version of the "TwoPartyTrade" flow and is a useful example of how both the
|
||||
// "collectSignaturesFlow" and "SignTransactionFlow" can be used in practise.
|
||||
object TestFlow {
|
||||
@InitiatingFlow
|
||||
@ -89,7 +91,7 @@ class CollectSignaturesFlowTests {
|
||||
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
|
||||
|
||||
val myInputKeys = state.participants.map { it.owningKey }
|
||||
val myKeys = myInputKeys + (identities[serviceHub.myInfo.legalIdentity] ?: serviceHub.myInfo.legalIdentity).owningKey
|
||||
val myKeys = myInputKeys + (identities[serviceHub.myInfo.chooseIdentity()] ?: serviceHub.myInfo.chooseIdentity()).owningKey
|
||||
val command = Command(DummyContract.Commands.Create(), myInputKeys)
|
||||
val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), command)
|
||||
val ptx = serviceHub.signInitialTransaction(builder)
|
||||
@ -145,7 +147,7 @@ class CollectSignaturesFlowTests {
|
||||
@Test
|
||||
fun `successfully collects two signatures`() {
|
||||
val bConfidentialIdentity = b.database.transaction {
|
||||
b.services.keyManagementService.freshKeyAndCert(b.info.legalIdentityAndCert, false)
|
||||
b.services.keyManagementService.freshKeyAndCert(b.info.chooseIdentityAndCert(), false)
|
||||
}
|
||||
a.database.transaction {
|
||||
// Normally this is handled by TransactionKeyFlow, but here we have to manually let A know about the identity
|
||||
@ -153,7 +155,7 @@ class CollectSignaturesFlowTests {
|
||||
}
|
||||
registerFlowOnAllNodes(TestFlowTwo.Responder::class)
|
||||
val magicNumber = 1337
|
||||
val parties = listOf(a.info.legalIdentity, bConfidentialIdentity.party, c.info.legalIdentity)
|
||||
val parties = listOf(a.info.chooseIdentity(), bConfidentialIdentity.party, c.info.chooseIdentity())
|
||||
val state = DummyContract.MultiOwnerState(magicNumber, parties)
|
||||
val flow = a.services.startFlow(TestFlowTwo.Initiator(state))
|
||||
mockNet.runNetwork()
|
||||
@ -165,7 +167,7 @@ class CollectSignaturesFlowTests {
|
||||
|
||||
@Test
|
||||
fun `no need to collect any signatures`() {
|
||||
val onePartyDummyContract = DummyContract.generateInitial(1337, notary, a.info.legalIdentity.ref(1))
|
||||
val onePartyDummyContract = DummyContract.generateInitial(1337, notary, a.info.chooseIdentity().ref(1))
|
||||
val ptx = a.services.signInitialTransaction(onePartyDummyContract)
|
||||
val flow = a.services.startFlow(CollectSignaturesFlow(ptx))
|
||||
mockNet.runNetwork()
|
||||
@ -177,7 +179,7 @@ class CollectSignaturesFlowTests {
|
||||
|
||||
@Test
|
||||
fun `fails when not signed by initiator`() {
|
||||
val onePartyDummyContract = DummyContract.generateInitial(1337, notary, a.info.legalIdentity.ref(1))
|
||||
val onePartyDummyContract = DummyContract.generateInitial(1337, notary, a.info.chooseIdentity().ref(1))
|
||||
val miniCorpServices = MockServices(MINI_CORP_KEY)
|
||||
val ptx = miniCorpServices.signInitialTransaction(onePartyDummyContract)
|
||||
val flow = a.services.startFlow(CollectSignaturesFlow(ptx))
|
||||
@ -190,9 +192,9 @@ class CollectSignaturesFlowTests {
|
||||
@Test
|
||||
fun `passes with multiple initial signatures`() {
|
||||
val twoPartyDummyContract = DummyContract.generateInitial(1337, notary,
|
||||
a.info.legalIdentity.ref(1),
|
||||
b.info.legalIdentity.ref(2),
|
||||
b.info.legalIdentity.ref(3))
|
||||
a.info.chooseIdentity().ref(1),
|
||||
b.info.chooseIdentity().ref(2),
|
||||
b.info.chooseIdentity().ref(3))
|
||||
val signedByA = a.services.signInitialTransaction(twoPartyDummyContract)
|
||||
val signedByBoth = b.services.addSignature(signedByA)
|
||||
val flow = a.services.startFlow(CollectSignaturesFlow(signedByBoth))
|
||||
@ -202,4 +204,3 @@ class CollectSignaturesFlowTests {
|
||||
println(result.sigs)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ import net.corda.node.internal.StartedNode
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.RPCDriverExposedDSLInterface
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.contracts.DummyContractV2
|
||||
import net.corda.testing.node.MockNetwork
|
||||
@ -73,11 +74,11 @@ class ContractUpgradeFlowTest {
|
||||
@Test
|
||||
fun `2 parties contract upgrade`() {
|
||||
// Create dummy contract.
|
||||
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, a.info.legalIdentity.ref(1), b.info.legalIdentity.ref(1))
|
||||
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, a.info.chooseIdentity().ref(1), b.info.chooseIdentity().ref(1))
|
||||
val signedByA = a.services.signInitialTransaction(twoPartyDummyContract)
|
||||
val stx = b.services.addSignature(signedByA)
|
||||
|
||||
a.services.startFlow(FinalityFlow(stx, setOf(a.info.legalIdentity, b.info.legalIdentity)))
|
||||
a.services.startFlow(FinalityFlow(stx, setOf(a.info.chooseIdentity(), b.info.chooseIdentity())))
|
||||
mockNet.runNetwork()
|
||||
|
||||
val atx = a.database.transaction { a.services.validatedTransactions.getTransaction(stx.id) }
|
||||
@ -143,7 +144,7 @@ class ContractUpgradeFlowTest {
|
||||
fun `2 parties contract upgrade using RPC`() {
|
||||
rpcDriver(initialiseSerialization = false) {
|
||||
// Create dummy contract.
|
||||
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, a.info.legalIdentity.ref(1), b.info.legalIdentity.ref(1))
|
||||
val twoPartyDummyContract = DummyContract.generateInitial(0, notary, a.info.chooseIdentity().ref(1), b.info.chooseIdentity().ref(1))
|
||||
val signedByA = a.services.signInitialTransaction(twoPartyDummyContract)
|
||||
val stx = b.services.addSignature(signedByA)
|
||||
|
||||
@ -156,7 +157,7 @@ class ContractUpgradeFlowTest {
|
||||
))
|
||||
val rpcA = startProxy(a, user)
|
||||
val rpcB = startProxy(b, user)
|
||||
val handle = rpcA.startFlow(::FinalityInvoker, stx, setOf(a.info.legalIdentity, b.info.legalIdentity))
|
||||
val handle = rpcA.startFlow(::FinalityInvoker, stx, setOf(a.info.chooseIdentity(), b.info.chooseIdentity()))
|
||||
mockNet.runNetwork()
|
||||
handle.returnValue.getOrThrow()
|
||||
|
||||
@ -218,6 +219,7 @@ class ContractUpgradeFlowTest {
|
||||
@Test
|
||||
fun `upgrade Cash to v2`() {
|
||||
// Create some cash.
|
||||
val chosenIdentity = a.info.chooseIdentity()
|
||||
val result = a.services.startFlow(CashIssueFlow(Amount(1000, USD), OpaqueBytes.of(1), notary)).resultFuture
|
||||
mockNet.runNetwork()
|
||||
val stx = result.getOrThrow().stx
|
||||
@ -232,7 +234,7 @@ class ContractUpgradeFlowTest {
|
||||
// Get contract state from the vault.
|
||||
val firstState = a.database.transaction { a.services.vaultQueryService.queryBy<ContractState>().states.single() }
|
||||
assertTrue(firstState.state.data is CashV2.State, "Contract state is upgraded to the new version.")
|
||||
assertEquals(Amount(1000000, USD).`issued by`(a.info.legalIdentity.ref(1)), (firstState.state.data as CashV2.State).amount, "Upgraded cash contain the correct amount.")
|
||||
assertEquals(Amount(1000000, USD).`issued by`(chosenIdentity.ref(1)), (firstState.state.data as CashV2.State).amount, "Upgraded cash contain the correct amount.")
|
||||
assertEquals<Collection<AbstractParty>>(listOf(anonymisedRecipient), (firstState.state.data as CashV2.State).owners, "Upgraded cash belongs to the right owner.")
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import net.corda.finance.GBP
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.After
|
||||
@ -42,9 +43,9 @@ class FinalityFlowTests {
|
||||
|
||||
@Test
|
||||
fun `finalise a simple transaction`() {
|
||||
val amount = Amount(1000, Issued(nodeA.info.legalIdentity.ref(0), GBP))
|
||||
val amount = Amount(1000, Issued(nodeA.info.chooseIdentity().ref(0), GBP))
|
||||
val builder = TransactionBuilder(notary)
|
||||
Cash().generateIssue(builder, amount, nodeB.info.legalIdentity, notary)
|
||||
Cash().generateIssue(builder, amount, nodeB.info.chooseIdentity(), notary)
|
||||
val stx = nodeA.services.signInitialTransaction(builder)
|
||||
val flow = nodeA.services.startFlow(FinalityFlow(stx))
|
||||
mockNet.runNetwork()
|
||||
@ -59,7 +60,7 @@ class FinalityFlowTests {
|
||||
|
||||
@Test
|
||||
fun `reject a transaction with unknown parties`() {
|
||||
val amount = Amount(1000, Issued(nodeA.info.legalIdentity.ref(0), GBP))
|
||||
val amount = Amount(1000, Issued(nodeA.info.chooseIdentity().ref(0), GBP))
|
||||
val fakeIdentity = ALICE // Alice isn't part of this network, so node A won't recognise them
|
||||
val builder = TransactionBuilder(notary)
|
||||
Cash().generateIssue(builder, amount, fakeIdentity, notary)
|
||||
|
@ -12,6 +12,7 @@ import net.corda.finance.flows.CashIssueAndPaymentFlow
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@ -39,8 +40,8 @@ class IdentitySyncFlowTests {
|
||||
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
|
||||
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
val alice: Party = aliceNode.services.myInfo.legalIdentity
|
||||
val bob: Party = bobNode.services.myInfo.legalIdentity
|
||||
val alice: Party = aliceNode.services.myInfo.chooseIdentity()
|
||||
val bob: Party = bobNode.services.myInfo.chooseIdentity()
|
||||
bobNode.internals.registerInitiatedFlow(Receive::class.java)
|
||||
|
||||
// Alice issues then pays some cash to a new confidential identity that Bob doesn't know about
|
||||
|
@ -8,6 +8,7 @@ import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.finance.GBP
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.After
|
||||
@ -43,11 +44,11 @@ class ManualFinalityFlowTests {
|
||||
|
||||
@Test
|
||||
fun `finalise a simple transaction`() {
|
||||
val amount = Amount(1000, Issued(nodeA.info.legalIdentity.ref(0), GBP))
|
||||
val amount = Amount(1000, Issued(nodeA.info.chooseIdentity().ref(0), GBP))
|
||||
val builder = TransactionBuilder(notary)
|
||||
Cash().generateIssue(builder, amount, nodeB.info.legalIdentity, notary)
|
||||
Cash().generateIssue(builder, amount, nodeB.info.chooseIdentity(), notary)
|
||||
val stx = nodeA.services.signInitialTransaction(builder)
|
||||
val flow = nodeA.services.startFlow(ManualFinalityFlow(stx, setOf(nodeC.info.legalIdentity)))
|
||||
val flow = nodeA.services.startFlow(ManualFinalityFlow(stx, setOf(nodeC.info.chooseIdentity())))
|
||||
mockNet.runNetwork()
|
||||
val result = flow.resultFuture.getOrThrow()
|
||||
val notarisedTx = result.single()
|
||||
|
@ -7,6 +7,7 @@ import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
@ -24,8 +25,9 @@ class SwapIdentitiesFlowTests {
|
||||
val notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
|
||||
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
val alice: Party = aliceNode.services.myInfo.legalIdentity
|
||||
val bob: Party = bobNode.services.myInfo.legalIdentity
|
||||
val alice: Party = aliceNode.services.myInfo.chooseIdentity()
|
||||
val bob: Party = bobNode.services.myInfo.chooseIdentity()
|
||||
mockNet.registerIdentities()
|
||||
|
||||
// Run the flows
|
||||
val requesterFlow = aliceNode.services.startFlow(SwapIdentitiesFlow(bob))
|
||||
|
@ -15,6 +15,7 @@ import net.corda.testing.DUMMY_NOTARY_KEY
|
||||
import net.corda.testing.MEGA_CORP
|
||||
import net.corda.testing.MEGA_CORP_KEY
|
||||
import net.corda.testing.MINI_CORP
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockServices
|
||||
@ -59,7 +60,7 @@ class ResolveTransactionsFlowTest {
|
||||
@Test
|
||||
fun `resolve from two hashes`() {
|
||||
val (stx1, stx2) = makeTransactions()
|
||||
val p = TestFlow(setOf(stx2.id), a.info.legalIdentity)
|
||||
val p = TestFlow(setOf(stx2.id), a.info.chooseIdentity())
|
||||
val future = b.services.startFlow(p).resultFuture
|
||||
mockNet.runNetwork()
|
||||
val results = future.getOrThrow()
|
||||
@ -74,7 +75,7 @@ class ResolveTransactionsFlowTest {
|
||||
@Test
|
||||
fun `dependency with an error`() {
|
||||
val stx = makeTransactions(signFirstTX = false).second
|
||||
val p = TestFlow(setOf(stx.id), a.info.legalIdentity)
|
||||
val p = TestFlow(setOf(stx.id), a.info.chooseIdentity())
|
||||
val future = b.services.startFlow(p).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertFailsWith(SignedTransaction.SignaturesMissingException::class) { future.getOrThrow() }
|
||||
@ -83,7 +84,7 @@ class ResolveTransactionsFlowTest {
|
||||
@Test
|
||||
fun `resolve from a signed transaction`() {
|
||||
val (stx1, stx2) = makeTransactions()
|
||||
val p = TestFlow(stx2, a.info.legalIdentity)
|
||||
val p = TestFlow(stx2, a.info.chooseIdentity())
|
||||
val future = b.services.startFlow(p).resultFuture
|
||||
mockNet.runNetwork()
|
||||
future.getOrThrow()
|
||||
@ -108,7 +109,7 @@ class ResolveTransactionsFlowTest {
|
||||
}
|
||||
cursor = stx
|
||||
}
|
||||
val p = TestFlow(setOf(cursor.id), a.info.legalIdentity, 40)
|
||||
val p = TestFlow(setOf(cursor.id), a.info.chooseIdentity(), 40)
|
||||
val future = b.services.startFlow(p).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertFailsWith<ResolveTransactionsFlow.ExcessivelyLargeTransactionGraph> { future.getOrThrow() }
|
||||
@ -132,7 +133,7 @@ class ResolveTransactionsFlowTest {
|
||||
a.services.recordTransactions(stx2, stx3)
|
||||
}
|
||||
|
||||
val p = TestFlow(setOf(stx3.id), a.info.legalIdentity)
|
||||
val p = TestFlow(setOf(stx3.id), a.info.chooseIdentity())
|
||||
val future = b.services.startFlow(p).resultFuture
|
||||
mockNet.runNetwork()
|
||||
future.getOrThrow()
|
||||
@ -154,7 +155,7 @@ class ResolveTransactionsFlowTest {
|
||||
a.services.attachments.importAttachment(makeJar())
|
||||
}
|
||||
val stx2 = makeTransactions(withAttachment = id).second
|
||||
val p = TestFlow(stx2, a.info.legalIdentity)
|
||||
val p = TestFlow(stx2, a.info.chooseIdentity())
|
||||
val future = b.services.startFlow(p).resultFuture
|
||||
mockNet.runNetwork()
|
||||
future.getOrThrow()
|
||||
|
@ -19,6 +19,7 @@ import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.persistence.NodeAttachmentService
|
||||
import net.corda.node.utilities.DatabaseTransactionManager
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@ -96,7 +97,7 @@ class AttachmentSerializationTest {
|
||||
|
||||
@InitiatingFlow
|
||||
private abstract class ClientLogic(server: StartedNode<*>) : FlowLogic<ClientResult>() {
|
||||
internal val server = server.info.legalIdentity
|
||||
internal val server = server.info.chooseIdentity()
|
||||
|
||||
@Suspendable
|
||||
internal fun communicate() {
|
||||
|
@ -27,5 +27,4 @@ Additional, ``ServiceHub`` exposes the following properties:
|
||||
* ``ServiceHub.toSignedTransaction`` to sign a ``TransactionBuilder`` and convert it into a ``SignedTransaction``
|
||||
* ``ServiceHub.createSignature`` and ``ServiceHub.addSignature`` to create and add signatures to a ``SignedTransaction``
|
||||
|
||||
Finally, ``ServiceHub`` exposes the node's legal identity key (via ``ServiceHub.legalIdentityKey``) and its notary
|
||||
identity key (via ``ServiceHub.notaryIdentityKey``).
|
||||
Finally, ``ServiceHub`` exposes notary identity key via ``ServiceHub.notaryIdentityKey``.
|
@ -67,7 +67,7 @@ class IntegrationTestingTutorial {
|
||||
(1..10).map { i ->
|
||||
aliceProxy.startFlow(::CashPaymentFlow,
|
||||
i.DOLLARS,
|
||||
bob.nodeInfo.legalIdentity,
|
||||
bob.nodeInfo.chooseIdentity(),
|
||||
true
|
||||
).returnValue
|
||||
}.transpose().getOrThrow()
|
||||
@ -89,7 +89,7 @@ class IntegrationTestingTutorial {
|
||||
|
||||
// START 5
|
||||
for (i in 1..10) {
|
||||
bobProxy.startFlow(::CashPaymentFlow, i.DOLLARS, alice.nodeInfo.legalIdentity).returnValue.getOrThrow()
|
||||
bobProxy.startFlow(::CashPaymentFlow, i.DOLLARS, alice.nodeInfo.chooseIdentity()).returnValue.getOrThrow()
|
||||
}
|
||||
|
||||
aliceVaultUpdates.expectEvents {
|
||||
|
@ -134,15 +134,14 @@ public class FlowCookbookJava {
|
||||
// We may also need to identify a specific counterparty.
|
||||
// Again, we do so using the network map.
|
||||
// DOCSTART 2
|
||||
Party namedCounterparty = getServiceHub().getNetworkMapCache().getNodeByLegalName(new CordaX500Name("NodeA", "London", "UK")).getLegalIdentity();
|
||||
Party keyedCounterparty = getServiceHub().getNetworkMapCache().getNodeByLegalIdentityKey(dummyPubKey).getLegalIdentity();
|
||||
Party firstCounterparty = getServiceHub().getNetworkMapCache().getPartyNodes().get(0).getLegalIdentity();
|
||||
Party namedCounterparty = getServiceHub().getIdentityService().partyFromX500Name(new CordaX500Name("NodeA", "London", "UK"));
|
||||
Party keyedCounterparty = getServiceHub().getIdentityService().partyFromKey(dummyPubKey);
|
||||
// DOCEND 2
|
||||
|
||||
// Finally, we can use the map to identify nodes providing a
|
||||
// specific service (e.g. a regulator or an oracle).
|
||||
// DOCSTART 3
|
||||
Party regulator = getServiceHub().getNetworkMapCache().getNodesWithService(ServiceType.Companion.getRegulator()).get(0).getLegalIdentity();
|
||||
Party regulator = getServiceHub().getNetworkMapCache().getPeersWithService(ServiceType.Companion.getRegulator()).get(0).getIdentity().getParty();
|
||||
// DOCEND 3
|
||||
|
||||
/*------------------------------
|
||||
@ -267,7 +266,7 @@ public class FlowCookbookJava {
|
||||
// matching every public key in all of the transaction's commands.
|
||||
// DOCSTART 24
|
||||
DummyContract.Commands.Create commandData = new DummyContract.Commands.Create();
|
||||
PublicKey ourPubKey = getServiceHub().getLegalIdentityKey();
|
||||
PublicKey ourPubKey = getServiceHub().getMyInfo().getLegalIdentitiesAndCerts().get(0).getOwningKey();
|
||||
PublicKey counterpartyPubKey = counterparty.getOwningKey();
|
||||
List<PublicKey> requiredSigners = ImmutableList.of(ourPubKey, counterpartyPubKey);
|
||||
Command<DummyContract.Commands.Create> ourCommand = new Command<>(commandData, requiredSigners);
|
||||
|
@ -113,7 +113,7 @@ fun generateTransactions(proxy: CordaRPCOps) {
|
||||
val issueRef = OpaqueBytes.of(0)
|
||||
val parties = proxy.networkMapSnapshot()
|
||||
val notary = parties.first { it.advertisedServices.any { it.info.type.isNotary() } }.notaryIdentity
|
||||
val me = proxy.nodeIdentity().legalIdentity
|
||||
val me = proxy.nodeInfo().legalIdentities.first()
|
||||
while (true) {
|
||||
Thread.sleep(1000)
|
||||
val random = SplittableRandom()
|
||||
|
@ -20,6 +20,7 @@ import net.corda.finance.flows.AbstractCashFlow
|
||||
import net.corda.finance.flows.CashException
|
||||
import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.testing.chooseIdentity
|
||||
import java.util.*
|
||||
|
||||
// DOCSTART CustomVaultQuery
|
||||
@ -139,7 +140,7 @@ object TopupIssuerFlow {
|
||||
val issueTx = subFlow(issueCashFlow)
|
||||
// NOTE: issueCashFlow performs a Broadcast (which stores a local copy of the txn to the ledger)
|
||||
// short-circuit when issuing to self
|
||||
if (issueTo == serviceHub.myInfo.legalIdentity)
|
||||
if (issueTo == serviceHub.myInfo.chooseIdentity())
|
||||
return issueTx
|
||||
// now invoke Cash subflow to Move issued assetType to issue requester
|
||||
progressTracker.currentStep = TRANSFERRING
|
||||
|
@ -112,18 +112,17 @@ object FlowCookbook {
|
||||
val firstNotary: Party = serviceHub.networkMapCache.notaryNodes[0].notaryIdentity
|
||||
// DOCEND 1
|
||||
|
||||
// We may also need to identify a specific counterparty. Again, we
|
||||
// do so using the network map.
|
||||
// We may also need to identify a specific counterparty. We
|
||||
// do so using identity service.
|
||||
// DOCSTART 2
|
||||
val namedCounterparty: Party? = serviceHub.networkMapCache.getNodeByLegalName(CordaX500Name(organisation = "NodeA", locality = "London", country = "UK"))?.legalIdentity
|
||||
val keyedCounterparty: Party? = serviceHub.networkMapCache.getNodeByLegalIdentityKey(dummyPubKey)?.legalIdentity
|
||||
val firstCounterparty: Party = serviceHub.networkMapCache.partyNodes[0].legalIdentity
|
||||
val namedCounterparty: Party? = serviceHub.identityService.partyFromX500Name(CordaX500Name(organisation = "NodeA", locality = "London", country = "UK"))
|
||||
val keyedCounterparty: Party? = serviceHub.identityService.partyFromKey(dummyPubKey)
|
||||
// DOCEND 2
|
||||
|
||||
// Finally, we can use the map to identify nodes providing a
|
||||
// specific service (e.g. a regulator or an oracle).
|
||||
// DOCSTART 3
|
||||
val regulator: Party = serviceHub.networkMapCache.getNodesWithService(ServiceType.regulator)[0].legalIdentity
|
||||
val regulator: Party = serviceHub.networkMapCache.getPeersWithService(ServiceType.regulator)[0].identity.party
|
||||
// DOCEND 3
|
||||
|
||||
/**-----------------------------
|
||||
@ -248,7 +247,7 @@ object FlowCookbook {
|
||||
// matching every public key in all of the transaction's commands.
|
||||
// DOCSTART 24
|
||||
val commandData: DummyContract.Commands.Create = DummyContract.Commands.Create()
|
||||
val ourPubKey: PublicKey = serviceHub.legalIdentityKey
|
||||
val ourPubKey: PublicKey = serviceHub.myInfo.legalIdentitiesAndCerts.first().owningKey
|
||||
val counterpartyPubKey: PublicKey = counterparty.owningKey
|
||||
val requiredSigners: List<PublicKey> = listOf(ourPubKey, counterpartyPubKey)
|
||||
val ourCommand: Command<DummyContract.Commands.Create> = Command(commandData, requiredSigners)
|
||||
|
@ -17,6 +17,7 @@ import net.corda.core.utilities.unwrap
|
||||
import net.corda.finance.contracts.asset.CASH_PROGRAM_ID
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.schemas.CashSchemaV1
|
||||
import net.corda.testing.chooseIdentity
|
||||
import java.util.*
|
||||
|
||||
@CordaSerializable
|
||||
@ -74,7 +75,7 @@ private fun prepareOurInputsAndOutputs(serviceHub: ServiceHub, lockId: UUID, req
|
||||
val outputs = if (residual > 0L) {
|
||||
// Build an output state for the residual change back to us
|
||||
val residualAmount = Amount(residual, sellAmount.token)
|
||||
val residualOutput = Cash.State(residualAmount, serviceHub.myInfo.legalIdentity)
|
||||
val residualOutput = Cash.State(residualAmount, serviceHub.myInfo.chooseIdentity())
|
||||
listOf(transferedFundsOutput, residualOutput)
|
||||
} else {
|
||||
listOf(transferedFundsOutput)
|
||||
@ -96,11 +97,11 @@ class ForeignExchangeFlow(val tradeId: String,
|
||||
// Select correct sides of the Fx exchange to query for.
|
||||
// Specifically we own the assets we wish to sell.
|
||||
// Also prepare the other side query
|
||||
val (localRequest, remoteRequest) = if (baseCurrencySeller == serviceHub.myInfo.legalIdentity) {
|
||||
val (localRequest, remoteRequest) = if (baseCurrencySeller == serviceHub.myInfo.chooseIdentity()) {
|
||||
val local = FxRequest(tradeId, baseCurrencyAmount, baseCurrencySeller, baseCurrencyBuyer)
|
||||
val remote = FxRequest(tradeId, quoteCurrencyAmount, baseCurrencyBuyer, baseCurrencySeller)
|
||||
Pair(local, remote)
|
||||
} else if (baseCurrencyBuyer == serviceHub.myInfo.legalIdentity) {
|
||||
} else if (baseCurrencyBuyer == serviceHub.myInfo.chooseIdentity()) {
|
||||
val local = FxRequest(tradeId, quoteCurrencyAmount, baseCurrencyBuyer, baseCurrencySeller)
|
||||
val remote = FxRequest(tradeId, baseCurrencyAmount, baseCurrencySeller, baseCurrencyBuyer)
|
||||
Pair(local, remote)
|
||||
@ -132,7 +133,7 @@ class ForeignExchangeFlow(val tradeId: String,
|
||||
>= remoteRequestWithNotary.amount.quantity) {
|
||||
"the provided inputs don't provide sufficient funds"
|
||||
}
|
||||
require(it.filter { it.owner == serviceHub.myInfo.legalIdentity }.
|
||||
require(it.filter { it.owner == serviceHub.myInfo.chooseIdentity() }.
|
||||
map { it.amount.quantity }.sum() == remoteRequestWithNotary.amount.quantity) {
|
||||
"the provided outputs don't provide the request quantity"
|
||||
}
|
||||
@ -205,7 +206,7 @@ class ForeignExchangeRemoteFlow(val source: Party) : FlowLogic<Unit>() {
|
||||
// the lifecycle of the Fx trades which would be included in the transaction
|
||||
|
||||
// Check request is for us
|
||||
require(serviceHub.myInfo.legalIdentity == it.owner) {
|
||||
require(serviceHub.myInfo.chooseIdentity() == it.owner) {
|
||||
"Request does not include the correct counterparty"
|
||||
}
|
||||
require(source == it.counterparty) {
|
||||
|
@ -17,6 +17,7 @@ import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.seconds
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.testing.chooseIdentity
|
||||
|
||||
// Minimal state model of a manual approval process
|
||||
@CordaSerializable
|
||||
@ -102,7 +103,7 @@ class SubmitTradeApprovalFlow(val tradeId: String,
|
||||
// Manufacture an initial state
|
||||
val tradeProposal = TradeApprovalContract.State(
|
||||
tradeId,
|
||||
serviceHub.myInfo.legalIdentity,
|
||||
serviceHub.myInfo.chooseIdentity(),
|
||||
counterparty)
|
||||
// identify a notary. This might also be done external to the flow
|
||||
val notary = serviceHub.networkMapCache.getAnyNotary()
|
||||
@ -113,7 +114,7 @@ class SubmitTradeApprovalFlow(val tradeId: String,
|
||||
// We can automatically sign as there is no untrusted data.
|
||||
val signedTx = serviceHub.signInitialTransaction(tx)
|
||||
// Notarise and distribute.
|
||||
subFlow(FinalityFlow(signedTx, setOf(serviceHub.myInfo.legalIdentity, counterparty)))
|
||||
subFlow(FinalityFlow(signedTx, setOf(serviceHub.myInfo.chooseIdentity(), counterparty)))
|
||||
// Return the initial state
|
||||
return signedTx.tx.outRef<TradeApprovalContract.State>(0)
|
||||
}
|
||||
@ -148,7 +149,7 @@ class SubmitCompletionFlow(val ref: StateRef, val verdict: WorkflowState) : Flow
|
||||
"Input trade not modifiable ${latestRecord.state.data.state}"
|
||||
}
|
||||
// Check we are the correct Party to run the protocol. Note they will counter check this too.
|
||||
require(latestRecord.state.data.counterparty == serviceHub.myInfo.legalIdentity) {
|
||||
require(latestRecord.state.data.counterparty == serviceHub.myInfo.chooseIdentity()) {
|
||||
"The counterparty must give the verdict"
|
||||
}
|
||||
|
||||
@ -170,7 +171,7 @@ class SubmitCompletionFlow(val ref: StateRef, val verdict: WorkflowState) : Flow
|
||||
latestRecord,
|
||||
StateAndContract(newState, TRADE_APPROVAL_PROGRAM_ID),
|
||||
Command(TradeApprovalContract.Commands.Completed(),
|
||||
listOf(serviceHub.myInfo.legalIdentity.owningKey, latestRecord.state.data.source.owningKey)))
|
||||
listOf(serviceHub.myInfo.chooseIdentity().owningKey, latestRecord.state.data.source.owningKey)))
|
||||
tx.setTimeWindow(serviceHub.clock.instant(), 60.seconds)
|
||||
// We can sign this transaction immediately as we have already checked all the fields and the decision
|
||||
// is ultimately a manual one from the caller.
|
||||
@ -213,7 +214,7 @@ class RecordCompletionFlow(val source: Party) : FlowLogic<Unit>() {
|
||||
// First we receive the verdict transaction signed by their single key
|
||||
val completeTx = receive<SignedTransaction>(source).unwrap {
|
||||
// Check the transaction is signed apart from our own key and the notary
|
||||
it.verifySignaturesExcept(serviceHub.myInfo.legalIdentity.owningKey, it.tx.notary!!.owningKey)
|
||||
it.verifySignaturesExcept(serviceHub.myInfo.chooseIdentity().owningKey, it.tx.notary!!.owningKey)
|
||||
// Check the transaction data is correctly formed
|
||||
val ltx = it.toLedgerTransaction(serviceHub, false)
|
||||
ltx.verify()
|
||||
@ -224,7 +225,7 @@ class RecordCompletionFlow(val source: Party) : FlowLogic<Unit>() {
|
||||
// Check the context dependent parts of the transaction as the
|
||||
// Contract verify method must not use serviceHub queries.
|
||||
val state = ltx.outRef<TradeApprovalContract.State>(0)
|
||||
require(state.state.data.source == serviceHub.myInfo.legalIdentity) {
|
||||
require(state.state.data.source == serviceHub.myInfo.chooseIdentity()) {
|
||||
"Proposal not one of our original proposals"
|
||||
}
|
||||
require(state.state.data.counterparty == source) {
|
||||
|
@ -13,6 +13,7 @@ import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.DUMMY_NOTARY_KEY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Assert
|
||||
@ -77,9 +78,9 @@ class CustomVaultQueryTest {
|
||||
|
||||
private fun topUpCurrencies() {
|
||||
val flowHandle1 = nodeA.services.startFlow(TopupIssuerFlow.TopupIssuanceRequester(
|
||||
nodeA.info.legalIdentity,
|
||||
nodeA.info.chooseIdentity(),
|
||||
OpaqueBytes.of(0x01),
|
||||
nodeA.info.legalIdentity,
|
||||
nodeA.info.chooseIdentity(),
|
||||
notaryNode.info.notaryIdentity))
|
||||
flowHandle1.resultFuture.getOrThrow()
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.DUMMY_NOTARY_KEY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@ -69,10 +70,10 @@ class FxTransactionBuildTutorialTest {
|
||||
|
||||
// Now run the actual Fx exchange
|
||||
val doIt = nodeA.services.startFlow(ForeignExchangeFlow("trade1",
|
||||
POUNDS(100).issuedBy(nodeB.info.legalIdentity.ref(0x01)),
|
||||
DOLLARS(200).issuedBy(nodeA.info.legalIdentity.ref(0x01)),
|
||||
nodeA.info.legalIdentity,
|
||||
nodeB.info.legalIdentity))
|
||||
POUNDS(100).issuedBy(nodeB.info.chooseIdentity().ref(0x01)),
|
||||
DOLLARS(200).issuedBy(nodeA.info.chooseIdentity().ref(0x01)),
|
||||
nodeA.info.chooseIdentity(),
|
||||
nodeB.info.chooseIdentity()))
|
||||
// wait for the flow to finish and the vault updates to be done
|
||||
doIt.resultFuture.getOrThrow()
|
||||
// Get the balances when the vault updates
|
||||
|
@ -14,6 +14,7 @@ import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.DUMMY_NOTARY_KEY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@ -55,7 +56,7 @@ class WorkflowTransactionBuildTutorialTest {
|
||||
// Setup a vault subscriber to wait for successful upload of the proposal to NodeB
|
||||
val nodeBVaultUpdate = nodeB.services.vaultService.updates.toFuture()
|
||||
// Kick of the proposal flow
|
||||
val flow1 = nodeA.services.startFlow(SubmitTradeApprovalFlow("1234", nodeB.info.legalIdentity))
|
||||
val flow1 = nodeA.services.startFlow(SubmitTradeApprovalFlow("1234", nodeB.info.chooseIdentity()))
|
||||
// Wait for the flow to finish
|
||||
val proposalRef = flow1.resultFuture.getOrThrow()
|
||||
val proposalLinearId = proposalRef.state.data.linearId
|
||||
@ -71,8 +72,8 @@ class WorkflowTransactionBuildTutorialTest {
|
||||
// Confirm the state as as expected
|
||||
assertEquals(WorkflowState.NEW, proposalRef.state.data.state)
|
||||
assertEquals("1234", proposalRef.state.data.tradeId)
|
||||
assertEquals(nodeA.info.legalIdentity, proposalRef.state.data.source)
|
||||
assertEquals(nodeB.info.legalIdentity, proposalRef.state.data.counterparty)
|
||||
assertEquals(nodeA.info.chooseIdentity(), proposalRef.state.data.source)
|
||||
assertEquals(nodeB.info.chooseIdentity(), proposalRef.state.data.counterparty)
|
||||
assertEquals(proposalRef, latestFromA)
|
||||
assertEquals(proposalRef, latestFromB)
|
||||
// Setup a vault subscriber to pause until the final update is in NodeA and NodeB
|
||||
@ -95,8 +96,8 @@ class WorkflowTransactionBuildTutorialTest {
|
||||
// Confirm the state is as expected
|
||||
assertEquals(WorkflowState.APPROVED, completedRef.state.data.state)
|
||||
assertEquals("1234", completedRef.state.data.tradeId)
|
||||
assertEquals(nodeA.info.legalIdentity, completedRef.state.data.source)
|
||||
assertEquals(nodeB.info.legalIdentity, completedRef.state.data.counterparty)
|
||||
assertEquals(nodeA.info.chooseIdentity(), completedRef.state.data.source)
|
||||
assertEquals(nodeB.info.chooseIdentity(), completedRef.state.data.counterparty)
|
||||
assertEquals(completedRef, finalFromA)
|
||||
assertEquals(completedRef, finalFromB)
|
||||
}
|
||||
|
@ -59,8 +59,6 @@ with the following:
|
||||
/** The flow logic is encapsulated within the call() method. */
|
||||
@Suspendable
|
||||
override fun call() {
|
||||
// We retrieve the required identities from the network map.
|
||||
val me = serviceHub.myInfo.legalIdentity
|
||||
val notary = serviceHub.networkMapCache.getAnyNotary()
|
||||
|
||||
// We create a transaction builder
|
||||
@ -124,7 +122,6 @@ with the following:
|
||||
@Override
|
||||
public Void call() throws FlowException {
|
||||
// We retrieve the required identities from the network map.
|
||||
final Party me = getServiceHub().getMyInfo().getLegalIdentity();
|
||||
final Party notary = getServiceHub().getNetworkMapCache().getAnyNotary(null);
|
||||
|
||||
// We create a transaction builder.
|
||||
|
@ -47,7 +47,7 @@ Next we create a state object and assign ourselves as the owner. For this exampl
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
val myIdentity = serviceHub.myInfo.legalIdentity
|
||||
val myIdentity = serviceHub.chooseIdentity()
|
||||
val state = DummyContract.SingleOwnerState(magicNumber = 42, owner = myIdentity.owningKey)
|
||||
|
||||
Then we add the state as the transaction output along with the relevant command. The state will automatically be assigned
|
||||
@ -63,7 +63,7 @@ We then sign the transaction, build and record it to our transaction storage:
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
val mySigningKey: PublicKey = serviceHub.legalIdentityKey
|
||||
val mySigningKey: PublicKey = serviceHub.chooseIdentity().owningKey
|
||||
val issueTransaction = serviceHub.toSignedTransaction(issueTransaction, mySigningKey)
|
||||
serviceHub.recordTransactions(issueTransaction)
|
||||
|
||||
|
@ -43,7 +43,7 @@ class CashExitFlow(val amount: Amount<Currency>, val issuerRef: OpaqueBytes, pro
|
||||
override fun call(): AbstractCashFlow.Result {
|
||||
progressTracker.currentStep = GENERATING_TX
|
||||
val builder = TransactionBuilder(notary = null as Party?)
|
||||
val issuer = serviceHub.myInfo.legalIdentity.ref(issuerRef)
|
||||
val issuer = ourIdentity.party.ref(issuerRef)
|
||||
val exitStates = CashSelection.getInstance({serviceHub.jdbcSession().metaData}).unconsumedCashStatesForSpending(serviceHub, amount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference))
|
||||
val signers = try {
|
||||
Cash().generateExit(
|
||||
|
@ -36,17 +36,15 @@ class CashIssueFlow(val amount: Amount<Currency>,
|
||||
|
||||
@Suspendable
|
||||
override fun call(): AbstractCashFlow.Result {
|
||||
val issuerCert = serviceHub.myInfo.legalIdentityAndCert
|
||||
|
||||
progressTracker.currentStep = GENERATING_TX
|
||||
val builder = TransactionBuilder(notary)
|
||||
val issuer = issuerCert.party.ref(issuerBankPartyRef)
|
||||
val signers = Cash().generateIssue(builder, amount.issuedBy(issuer), issuerCert.party, notary)
|
||||
val issuer = ourIdentity.party.ref(issuerBankPartyRef)
|
||||
val signers = Cash().generateIssue(builder, amount.issuedBy(issuer), ourIdentity.party, notary)
|
||||
progressTracker.currentStep = SIGNING_TX
|
||||
val tx = serviceHub.signInitialTransaction(builder, signers)
|
||||
progressTracker.currentStep = FINALISING_TX
|
||||
subFlow(FinalityFlow(tx))
|
||||
return Result(tx, issuerCert.party)
|
||||
return Result(tx, ourIdentity.party)
|
||||
}
|
||||
|
||||
@CordaSerializable
|
||||
|
@ -54,7 +54,7 @@ object TwoPartyDealFlow {
|
||||
@Suspendable override fun call(): SignedTransaction {
|
||||
progressTracker.currentStep = GENERATING_ID
|
||||
val txIdentities = subFlow(SwapIdentitiesFlow(otherParty))
|
||||
val anonymousMe = txIdentities.get(serviceHub.myInfo.legalIdentity) ?: serviceHub.myInfo.legalIdentity.anonymise()
|
||||
val anonymousMe = txIdentities.get(ourIdentity.party) ?: ourIdentity.party.anonymise()
|
||||
val anonymousCounterparty = txIdentities.get(otherParty) ?: otherParty.anonymise()
|
||||
progressTracker.currentStep = SENDING_PROPOSAL
|
||||
// Make the first message we'll send to kick off the flow.
|
||||
@ -118,7 +118,7 @@ object TwoPartyDealFlow {
|
||||
logger.trace { "Got signatures from other party, verifying ... " }
|
||||
|
||||
progressTracker.currentStep = RECORDING
|
||||
val ftx = subFlow(FinalityFlow(stx, setOf(otherParty, serviceHub.myInfo.legalIdentity))).single()
|
||||
val ftx = subFlow(FinalityFlow(stx, setOf(otherParty, ourIdentity.party))).single()
|
||||
|
||||
logger.trace { "Recorded transaction." }
|
||||
|
||||
@ -150,7 +150,7 @@ object TwoPartyDealFlow {
|
||||
val wellKnownOtherParty = serviceHub.identityService.partyFromAnonymous(it.primaryIdentity)
|
||||
val wellKnownMe = serviceHub.identityService.partyFromAnonymous(it.secondaryIdentity)
|
||||
require(wellKnownOtherParty == otherParty)
|
||||
require(wellKnownMe == serviceHub.myInfo.legalIdentity)
|
||||
require(wellKnownMe == ourIdentity.party)
|
||||
validateHandshake(it)
|
||||
}
|
||||
}
|
||||
@ -197,7 +197,7 @@ object TwoPartyDealFlow {
|
||||
// We set the transaction's time-window: it may be that none of the contracts need this!
|
||||
// But it can't hurt to have one.
|
||||
ptx.setTimeWindow(serviceHub.clock.instant(), 30.seconds)
|
||||
return Triple(ptx, arrayListOf(deal.participants.single { it == serviceHub.myInfo.legalIdentity as AbstractParty }.owningKey), emptyList())
|
||||
return Triple(ptx, arrayListOf(deal.participants.single { it == ourIdentity.party as AbstractParty }.owningKey), emptyList())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ object TwoPartyTradeFlow {
|
||||
val notaryNode: NodeInfo,
|
||||
val assetToSell: StateAndRef<OwnableState>,
|
||||
val price: Amount<Currency>,
|
||||
val me: PartyAndCertificate,
|
||||
val myParty: PartyAndCertificate, // TODO Left because in tests it's used to pass anonymous party.
|
||||
override val progressTracker: ProgressTracker = Seller.tracker()) : FlowLogic<SignedTransaction>() {
|
||||
|
||||
companion object {
|
||||
@ -82,7 +82,7 @@ object TwoPartyTradeFlow {
|
||||
override fun call(): SignedTransaction {
|
||||
progressTracker.currentStep = AWAITING_PROPOSAL
|
||||
// Make the first message we'll send to kick off the flow.
|
||||
val hello = SellerTradeInfo(price, me)
|
||||
val hello = SellerTradeInfo(price, myParty)
|
||||
// What we get back from the other side is a transaction that *might* be valid and acceptable to us,
|
||||
// but we must check it out thoroughly before we sign!
|
||||
// SendTransactionFlow allows otherParty to access our data to resolve the transaction.
|
||||
@ -107,7 +107,7 @@ object TwoPartyTradeFlow {
|
||||
}
|
||||
}
|
||||
|
||||
if (stx.tx.outputStates.sumCashBy(me.party).withoutIssuer() != price)
|
||||
if (stx.tx.outputStates.sumCashBy(myParty.party).withoutIssuer() != price)
|
||||
throw FlowException("Transaction is not sending us the right amount of cash")
|
||||
}
|
||||
}
|
||||
@ -161,10 +161,9 @@ object TwoPartyTradeFlow {
|
||||
|
||||
// Create the identity we'll be paying to, and send the counterparty proof we own the identity
|
||||
val buyerAnonymousIdentity = if (anonymous)
|
||||
serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.legalIdentityAndCert, false)
|
||||
serviceHub.keyManagementService.freshKeyAndCert(ourIdentity, false)
|
||||
else
|
||||
serviceHub.myInfo.legalIdentityAndCert
|
||||
|
||||
ourIdentity
|
||||
// Put together a proposed transaction that performs the trade, and sign it.
|
||||
progressTracker.currentStep = SIGNING
|
||||
val (ptx, cashSigningPubKeys) = assembleSharedTX(assetForSale, tradeRequest, buyerAnonymousIdentity)
|
||||
|
@ -243,7 +243,7 @@ class CommercialPaperTestsGeneric {
|
||||
|
||||
// BigCorp™ issues $10,000 of commercial paper, to mature in 30 days, owned initially by itself.
|
||||
val faceValue = 10000.DOLLARS `issued by` DUMMY_CASH_ISSUER
|
||||
val issuance = bigCorpServices.myInfo.legalIdentity.ref(1)
|
||||
val issuance = bigCorpServices.myInfo.chooseIdentity().ref(1)
|
||||
val issueBuilder = CommercialPaper().generateIssue(issuance, faceValue, TEST_TX_TIME + 30.days, DUMMY_NOTARY)
|
||||
issueBuilder.setTimeWindow(TEST_TX_TIME, 30.seconds)
|
||||
val issuePtx = bigCorpServices.signInitialTransaction(issueBuilder)
|
||||
|
@ -7,6 +7,7 @@ import net.corda.finance.DOLLARS
|
||||
import net.corda.finance.`issued by`
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetwork.MockNode
|
||||
@ -31,7 +32,7 @@ class CashExitFlowTests {
|
||||
notaryNode = nodes.notaryNode
|
||||
bankOfCordaNode = nodes.partyNodes[0]
|
||||
notary = notaryNode.info.notaryIdentity
|
||||
bankOfCorda = bankOfCordaNode.info.legalIdentity
|
||||
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
|
||||
|
||||
mockNet.runNetwork()
|
||||
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture
|
||||
|
@ -7,6 +7,7 @@ import net.corda.finance.DOLLARS
|
||||
import net.corda.finance.`issued by`
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetwork.MockNode
|
||||
@ -29,7 +30,7 @@ class CashIssueFlowTests {
|
||||
notaryNode = nodes.notaryNode
|
||||
bankOfCordaNode = nodes.partyNodes[0]
|
||||
notary = notaryNode.info.notaryIdentity
|
||||
bankOfCorda = bankOfCordaNode.info.legalIdentity
|
||||
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
|
||||
|
||||
mockNet.runNetwork()
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import net.corda.finance.DOLLARS
|
||||
import net.corda.finance.`issued by`
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.expect
|
||||
import net.corda.testing.expectEvents
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||
@ -36,7 +37,7 @@ class CashPaymentFlowTests {
|
||||
notaryNode = nodes.notaryNode
|
||||
bankOfCordaNode = nodes.partyNodes[0]
|
||||
notary = notaryNode.info.notaryIdentity
|
||||
bankOfCorda = bankOfCordaNode.info.legalIdentity
|
||||
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
|
||||
|
||||
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture
|
||||
mockNet.runNetwork()
|
||||
@ -50,7 +51,7 @@ class CashPaymentFlowTests {
|
||||
|
||||
@Test
|
||||
fun `pay some cash`() {
|
||||
val payTo = notaryNode.info.legalIdentity
|
||||
val payTo = notaryNode.info.chooseIdentity()
|
||||
val expectedPayment = 500.DOLLARS
|
||||
val expectedChange = 1500.DOLLARS
|
||||
|
||||
@ -90,7 +91,7 @@ class CashPaymentFlowTests {
|
||||
|
||||
@Test
|
||||
fun `pay more than we have`() {
|
||||
val payTo = notaryNode.info.legalIdentity
|
||||
val payTo = notaryNode.info.chooseIdentity()
|
||||
val expected = 4000.DOLLARS
|
||||
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected,
|
||||
payTo)).resultFuture
|
||||
@ -102,7 +103,7 @@ class CashPaymentFlowTests {
|
||||
|
||||
@Test
|
||||
fun `pay zero cash`() {
|
||||
val payTo = notaryNode.info.legalIdentity
|
||||
val payTo = notaryNode.info.chooseIdentity()
|
||||
val expected = 0.DOLLARS
|
||||
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected,
|
||||
payTo)).resultFuture
|
||||
|
@ -1,11 +1,11 @@
|
||||
package net.corda.nodeapi
|
||||
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.utilities.toBase58String
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.messaging.MessageRecipientGroup
|
||||
import net.corda.core.messaging.MessageRecipients
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.internal.read
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
@ -29,8 +29,7 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
|
||||
const val PEER_USER = "SystemUsers/Peer"
|
||||
|
||||
const val INTERNAL_PREFIX = "internal."
|
||||
const val PEERS_PREFIX = "${INTERNAL_PREFIX}peers."
|
||||
const val SERVICES_PREFIX = "${INTERNAL_PREFIX}services."
|
||||
const val PEERS_PREFIX = "${INTERNAL_PREFIX}peers." //TODO Come up with better name for common peers/services queue
|
||||
const val IP_REQUEST_PREFIX = "ip."
|
||||
const val P2P_QUEUE = "p2p.inbound"
|
||||
const val NOTIFICATIONS_ADDRESS = "${INTERNAL_PREFIX}activemq.notifications"
|
||||
@ -64,13 +63,9 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
|
||||
@CordaSerializable
|
||||
data class NodeAddress(override val queueName: String, override val hostAndPort: NetworkHostAndPort) : ArtemisPeerAddress {
|
||||
companion object {
|
||||
fun asPeer(peerIdentity: PublicKey, hostAndPort: NetworkHostAndPort): NodeAddress {
|
||||
fun asSingleNode(peerIdentity: PublicKey, hostAndPort: NetworkHostAndPort): NodeAddress {
|
||||
return NodeAddress("$PEERS_PREFIX${peerIdentity.toBase58String()}", hostAndPort)
|
||||
}
|
||||
|
||||
fun asService(serviceIdentity: PublicKey, hostAndPort: NetworkHostAndPort): NodeAddress {
|
||||
return NodeAddress("$SERVICES_PREFIX${serviceIdentity.toBase58String()}", hostAndPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +79,7 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
|
||||
* @param identity The service identity's owning key.
|
||||
*/
|
||||
data class ServiceAddress(val identity: PublicKey) : ArtemisAddress, MessageRecipientGroup {
|
||||
override val queueName: String = "$SERVICES_PREFIX${identity.toBase58String()}"
|
||||
override val queueName: String = "$PEERS_PREFIX${identity.toBase58String()}"
|
||||
}
|
||||
|
||||
/** The config object is used to pass in the passwords for the certificate KeyStore and TrustStore */
|
||||
@ -106,11 +101,12 @@ abstract class ArtemisMessagingComponent : SingletonSerializeAsToken() {
|
||||
}
|
||||
}
|
||||
|
||||
fun getArtemisPeerAddress(nodeInfo: NodeInfo): ArtemisPeerAddress {
|
||||
return if (nodeInfo.advertisedServices.any { it.info.type == ServiceType.networkMap }) {
|
||||
NetworkMapAddress(nodeInfo.addresses.first())
|
||||
// Used for bridges creation.
|
||||
fun getArtemisPeerAddress(party: Party, address: NetworkHostAndPort, netMapName: CordaX500Name? = null): ArtemisPeerAddress {
|
||||
return if (party.name == netMapName) {
|
||||
NetworkMapAddress(address)
|
||||
} else {
|
||||
NodeAddress.asPeer(nodeInfo.legalIdentity.owningKey, nodeInfo.addresses.first())
|
||||
NodeAddress.asSingleNode(party.owningKey, address) // It also takes care of services nodes treated as peer nodes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import org.bouncycastle.asn1.x500.X500Name
|
||||
sealed class ConnectionDirection {
|
||||
data class Inbound(val acceptorFactoryClassName: String) : ConnectionDirection()
|
||||
data class Outbound(
|
||||
val expectedCommonName: CordaX500Name? = null,
|
||||
val expectedCommonNames: Set<CordaX500Name> = emptySet(), // TODO SNI? Or we need a notion of node's network identity?
|
||||
val connectorFactoryClassName: String = NettyConnectorFactory::class.java.name
|
||||
) : ConnectionDirection()
|
||||
}
|
||||
@ -67,7 +67,7 @@ class ArtemisTcpTransport {
|
||||
TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME to CIPHER_SUITES.joinToString(","),
|
||||
TransportConstants.ENABLED_PROTOCOLS_PROP_NAME to "TLSv1.2",
|
||||
TransportConstants.NEED_CLIENT_AUTH_PROP_NAME to true,
|
||||
VERIFY_PEER_LEGAL_NAME to (direction as? ConnectionDirection.Outbound)?.expectedCommonName
|
||||
VERIFY_PEER_LEGAL_NAME to (direction as? ConnectionDirection.Outbound)?.expectedCommonNames
|
||||
)
|
||||
options.putAll(tlsOptions)
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import net.corda.testing.BOB
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.driver.driver
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
@ -30,7 +31,7 @@ class CordappScanningDriverTest {
|
||||
val initiatedFlowClass = alice.rpcClientToNode()
|
||||
.start(user.username, user.password)
|
||||
.proxy
|
||||
.startFlow(::ReceiveFlow, bob.nodeInfo.legalIdentity)
|
||||
.startFlow(::ReceiveFlow, bob.nodeInfo.chooseIdentity())
|
||||
.returnValue
|
||||
assertThat(initiatedFlowClass.getOrThrow()).isEqualTo(SendSubClassFlow::class.java.name)
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import net.corda.finance.flows.CashPaymentFlow
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.driver.NodeHandle
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.performance.div
|
||||
@ -116,7 +117,7 @@ class NodePerformanceTests {
|
||||
doneFutures.transpose().get()
|
||||
println("STARTING PAYMENT")
|
||||
startPublishingFixedRateInjector(metricRegistry, 8, 5.minutes, 100L / TimeUnit.SECONDS) {
|
||||
connection.proxy.startFlow(::CashPaymentFlow, 1.DOLLARS, a.nodeInfo.legalIdentity).returnValue.get()
|
||||
connection.proxy.startFlow(::CashPaymentFlow, 1.DOLLARS, a.nodeInfo.chooseIdentity()).returnValue.get()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ class AdvertisedServiceTests {
|
||||
fun `service is accessible through getAnyServiceOfType`() {
|
||||
driver(startNodesInProcess = true) {
|
||||
val bankA = startNode(rpcUsers = listOf(User(user, pass, setOf(startFlowPermission<ServiceTypeCheckingFlow>())))).get()
|
||||
startNode(advertisedServices = setOf(ServiceInfo(serviceType, serviceName))).get()
|
||||
startNode(providedName = serviceName, advertisedServices = setOf(ServiceInfo(serviceType))).get()
|
||||
bankA.rpcClientToNode().use(user, pass) { connection ->
|
||||
val result = connection.proxy.startFlow(::ServiceTypeCheckingFlow).returnValue.get()
|
||||
assertTrue(result)
|
||||
|
@ -23,6 +23,7 @@ import net.corda.node.services.transactions.BFTNonValidatingNotaryService
|
||||
import net.corda.node.services.transactions.minClusterSize
|
||||
import net.corda.node.services.transactions.minCorrectReplicas
|
||||
import net.corda.node.utilities.ServiceIdentityGenerator
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
@ -53,11 +54,12 @@ class BFTNotaryServiceTests {
|
||||
replicaIds.map { mockNet.baseDirectory(mockNet.nextNodeId + it) },
|
||||
serviceType.id,
|
||||
clusterName)
|
||||
val bftNotaryService = ServiceInfo(serviceType, clusterName)
|
||||
val bftNotaryService = ServiceInfo(serviceType)
|
||||
val notaryClusterAddresses = replicaIds.map { NetworkHostAndPort("localhost", 11000 + it * 10) }
|
||||
replicaIds.forEach { replicaId ->
|
||||
mockNet.createNode(
|
||||
node.network.myAddress,
|
||||
legalName = clusterName.copy(organisation = clusterName.organisation + replicaId),
|
||||
advertisedServices = bftNotaryService,
|
||||
configOverrides = {
|
||||
whenever(it.bftSMaRt).thenReturn(BFTSMaRtConfiguration(replicaId, false, exposeRaces))
|
||||
@ -73,7 +75,7 @@ class BFTNotaryServiceTests {
|
||||
val notary = bftNotaryCluster(minClusterSize(1), true) // This true adds a sleep to expose the race.
|
||||
val f = node.run {
|
||||
val trivialTx = signInitialTransaction(notary) {
|
||||
addOutputState(DummyContract.SingleOwnerState(owner = info.legalIdentity), DUMMY_PROGRAM_ID)
|
||||
addOutputState(DummyContract.SingleOwnerState(owner = info.chooseIdentity()), DUMMY_PROGRAM_ID)
|
||||
}
|
||||
// Create a new consensus while the redundant replica is sleeping:
|
||||
services.startFlow(NotaryFlow.Client(trivialTx)).resultFuture
|
||||
@ -97,7 +99,7 @@ class BFTNotaryServiceTests {
|
||||
val notary = bftNotaryCluster(clusterSize)
|
||||
node.run {
|
||||
val issueTx = signInitialTransaction(notary) {
|
||||
addOutputState(DummyContract.SingleOwnerState(owner = info.legalIdentity), DUMMY_PROGRAM_ID)
|
||||
addOutputState(DummyContract.SingleOwnerState(owner = (info.chooseIdentity())), DUMMY_PROGRAM_ID)
|
||||
}
|
||||
database.transaction {
|
||||
services.recordTransactions(issueTx)
|
||||
@ -132,7 +134,7 @@ class BFTNotaryServiceTests {
|
||||
assertEquals(StateRef(issueTx.id, 0), stateRef)
|
||||
assertEquals(spendTxs[successfulIndex].id, consumingTx.id)
|
||||
assertEquals(0, consumingTx.inputIndex)
|
||||
assertEquals(info.legalIdentity, consumingTx.requestingParty)
|
||||
assertEquals(info.chooseIdentity(), consumingTx.requestingParty)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -145,7 +147,7 @@ private fun StartedNode<*>.signInitialTransaction(
|
||||
): SignedTransaction {
|
||||
return services.signInitialTransaction(
|
||||
TransactionBuilder(notary).apply {
|
||||
addCommand(dummyCommand(services.legalIdentityKey))
|
||||
addCommand(dummyCommand(services.myInfo.chooseIdentity().owningKey))
|
||||
block()
|
||||
})
|
||||
}
|
||||
|
@ -2,11 +2,11 @@ package net.corda.node.services
|
||||
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.internal.bufferUntilSubscribed
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.messaging.StateMachineUpdate
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.finance.POUNDS
|
||||
@ -29,7 +29,7 @@ class DistributedServiceTests : DriverBasedTest() {
|
||||
lateinit var notaries: List<NodeHandle.OutOfProcess>
|
||||
lateinit var aliceProxy: CordaRPCOps
|
||||
lateinit var raftNotaryIdentity: Party
|
||||
lateinit var notaryStateMachines: Observable<Pair<NodeInfo, StateMachineUpdate>>
|
||||
lateinit var notaryStateMachines: Observable<Pair<Party, StateMachineUpdate>>
|
||||
|
||||
override fun setup() = driver {
|
||||
// Start Alice and 3 notaries in a RAFT cluster
|
||||
@ -51,8 +51,13 @@ class DistributedServiceTests : DriverBasedTest() {
|
||||
raftNotaryIdentity = notaryIdentity
|
||||
notaries = notaryNodes.map { it as NodeHandle.OutOfProcess }
|
||||
|
||||
val notariesIdentities = notaries.fold(HashSet<PartyAndCertificate>()) {
|
||||
acc, elem -> acc.addAll(elem.nodeInfo.legalIdentitiesAndCerts)
|
||||
acc
|
||||
}
|
||||
assertEquals(notaries.size, clusterSize)
|
||||
assertEquals(notaries.size, notaries.map { it.nodeInfo.legalIdentity }.toSet().size)
|
||||
// Check that each notary has different identity as a node.
|
||||
assertEquals(notaries.size, notariesIdentities.size - notaries[0].nodeInfo.advertisedServices.size)
|
||||
|
||||
// Connect to Alice and the notaries
|
||||
fun connectRpc(node: NodeHandle): CordaRPCOps {
|
||||
@ -62,7 +67,7 @@ class DistributedServiceTests : DriverBasedTest() {
|
||||
aliceProxy = connectRpc(alice)
|
||||
val rpcClientsToNotaries = notaries.map(::connectRpc)
|
||||
notaryStateMachines = Observable.from(rpcClientsToNotaries.map { proxy ->
|
||||
proxy.stateMachinesFeed().updates.map { Pair(proxy.nodeIdentity(), it) }
|
||||
proxy.stateMachinesFeed().updates.map { Pair(proxy.nodeInfo().chooseIdentity(), it) }
|
||||
}).flatMap { it.onErrorResumeNext(Observable.empty()) }.bufferUntilSubscribed()
|
||||
|
||||
runTest()
|
||||
@ -82,10 +87,10 @@ class DistributedServiceTests : DriverBasedTest() {
|
||||
// The state machines added in the notaries should map one-to-one to notarisation requests
|
||||
val notarisationsPerNotary = HashMap<Party, Int>()
|
||||
notaryStateMachines.expectEvents(isStrict = false) {
|
||||
replicate<Pair<NodeInfo, StateMachineUpdate>>(50) {
|
||||
replicate<Pair<Party, StateMachineUpdate>>(50) {
|
||||
expect(match = { it.second is StateMachineUpdate.Added }) { (notary, update) ->
|
||||
update as StateMachineUpdate.Added
|
||||
notarisationsPerNotary.compute(notary.legalIdentity) { _, number -> number?.plus(1) ?: 1 }
|
||||
notarisationsPerNotary.compute(notary) { _, number -> number?.plus(1) ?: 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -120,10 +125,10 @@ class DistributedServiceTests : DriverBasedTest() {
|
||||
|
||||
val notarisationsPerNotary = HashMap<Party, Int>()
|
||||
notaryStateMachines.expectEvents(isStrict = false) {
|
||||
replicate<Pair<NodeInfo, StateMachineUpdate>>(30) {
|
||||
replicate<Pair<Party, StateMachineUpdate>>(30) {
|
||||
expect(match = { it.second is StateMachineUpdate.Added }) { (notary, update) ->
|
||||
update as StateMachineUpdate.Added
|
||||
notarisationsPerNotary.compute(notary.legalIdentity) { _, number -> number?.plus(1) ?: 1 }
|
||||
notarisationsPerNotary.compute(notary) { _, number -> number?.plus(1) ?: 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -137,6 +142,6 @@ class DistributedServiceTests : DriverBasedTest() {
|
||||
}
|
||||
|
||||
private fun paySelf(amount: Amount<Currency>) {
|
||||
aliceProxy.startFlow(::CashPaymentFlow, amount, alice.nodeInfo.legalIdentity).returnValue.getOrThrow()
|
||||
aliceProxy.startFlow(::CashPaymentFlow, amount, alice.nodeInfo.chooseIdentity()).returnValue.getOrThrow()
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,9 @@ import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.NodeBasedTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import java.util.*
|
||||
import kotlin.test.assertEquals
|
||||
@ -25,6 +27,7 @@ import kotlin.test.assertFailsWith
|
||||
class RaftNotaryServiceTests : NodeBasedTest() {
|
||||
private val notaryName = CordaX500Name(organisation = "RAFT Notary Service", locality = "London", country = "GB")
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
fun `detect double spend`() {
|
||||
val (bankA) = listOf(
|
||||
@ -38,16 +41,16 @@ class RaftNotaryServiceTests : NodeBasedTest() {
|
||||
|
||||
val firstTxBuilder = TransactionBuilder(notaryParty)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(bankA.services.legalIdentityKey))
|
||||
.addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey))
|
||||
val firstSpendTx = bankA.services.signInitialTransaction(firstTxBuilder)
|
||||
|
||||
val firstSpend = bankA.services.startFlow(NotaryFlow.Client(firstSpendTx))
|
||||
firstSpend.resultFuture.getOrThrow()
|
||||
|
||||
val secondSpendBuilder = TransactionBuilder(notaryParty).withItems(inputState).run {
|
||||
val dummyState = DummyContract.SingleOwnerState(0, bankA.info.legalIdentity)
|
||||
val dummyState = DummyContract.SingleOwnerState(0, bankA.info.chooseIdentity())
|
||||
addOutputState(dummyState, DUMMY_PROGRAM_ID)
|
||||
addCommand(dummyCommand(bankA.services.legalIdentityKey))
|
||||
addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey))
|
||||
this
|
||||
}
|
||||
val secondSpendTx = bankA.services.signInitialTransaction(secondSpendBuilder)
|
||||
@ -60,7 +63,7 @@ class RaftNotaryServiceTests : NodeBasedTest() {
|
||||
|
||||
private fun issueState(node: StartedNode<*>, notary: Party): StateAndRef<*> {
|
||||
return node.database.transaction {
|
||||
val builder = DummyContract.generateInitial(Random().nextInt(), notary, node.info.legalIdentity.ref(0))
|
||||
val builder = DummyContract.generateInitial(Random().nextInt(), notary, node.info.chooseIdentity().ref(0))
|
||||
val stx = node.services.signInitialTransaction(builder)
|
||||
node.services.recordTransactions(stx)
|
||||
StateAndRef(builder.outputStates().first(), StateRef(stx.id, 0))
|
||||
|
@ -9,6 +9,7 @@ import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.NodeBasedTest
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
@ -21,7 +22,7 @@ class FlowVersioningTest : NodeBasedTest() {
|
||||
startNode(BOB.name, platformVersion = 3)).transpose().getOrThrow()
|
||||
bob.internals.installCoreFlow(PretendInitiatingCoreFlow::class, ::PretendInitiatedCoreFlow)
|
||||
val (alicePlatformVersionAccordingToBob, bobPlatformVersionAccordingToAlice) = alice.services.startFlow(
|
||||
PretendInitiatingCoreFlow(bob.info.legalIdentity)).resultFuture.getOrThrow()
|
||||
PretendInitiatingCoreFlow(bob.info.chooseIdentity())).resultFuture.getOrThrow()
|
||||
assertThat(alicePlatformVersionAccordingToBob).isEqualTo(2)
|
||||
assertThat(bobPlatformVersionAccordingToAlice).isEqualTo(3)
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import net.corda.testing.BOB
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.aliceBobAndNotary
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DummyState
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.dummyCommand
|
||||
@ -28,14 +29,14 @@ class LargeTransactionsTest {
|
||||
override fun call() {
|
||||
val tx = TransactionBuilder(notary = DUMMY_NOTARY)
|
||||
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
|
||||
.addCommand(dummyCommand(serviceHub.legalIdentityKey))
|
||||
.addCommand(dummyCommand(serviceHub.myInfo.chooseIdentity().owningKey))
|
||||
.addAttachment(hash1)
|
||||
.addAttachment(hash2)
|
||||
.addAttachment(hash3)
|
||||
.addAttachment(hash4)
|
||||
val stx = serviceHub.signInitialTransaction(tx, serviceHub.legalIdentityKey)
|
||||
val stx = serviceHub.signInitialTransaction(tx, serviceHub.myInfo.chooseIdentity().owningKey)
|
||||
// Send to the other side and wait for it to trigger resolution from us.
|
||||
val bob = serviceHub.networkMapCache.getNodeByLegalName(BOB.name)!!.legalIdentity
|
||||
val bob = serviceHub.identityService.partyFromX500Name(BOB.name)!!
|
||||
subFlow(SendTransactionFlow(bob, stx))
|
||||
receive<Unit>(bob)
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import net.corda.nodeapi.ArtemisMessagingComponent.Companion.PEERS_PREFIX
|
||||
import net.corda.nodeapi.RPCApi
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.nodeapi.config.SSLConfiguration
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.configureTestSSL
|
||||
import net.corda.testing.messaging.SimpleMQClient
|
||||
import net.corda.testing.node.NodeBasedTest
|
||||
@ -86,7 +87,7 @@ abstract class MQSecurityTest : NodeBasedTest() {
|
||||
@Test
|
||||
fun `create queue for peer which has not been communicated with`() {
|
||||
val bob = startNode(BOB.name).getOrThrow()
|
||||
assertAllQueueCreationAttacksFail("$PEERS_PREFIX${bob.info.legalIdentity.owningKey.toBase58String()}")
|
||||
assertAllQueueCreationAttacksFail("$PEERS_PREFIX${bob.info.chooseIdentity().owningKey.toBase58String()}")
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -219,7 +220,7 @@ abstract class MQSecurityTest : NodeBasedTest() {
|
||||
private fun startBobAndCommunicateWithAlice(): Party {
|
||||
val bob = startNode(BOB.name).getOrThrow()
|
||||
bob.internals.registerInitiatedFlow(ReceiveFlow::class.java)
|
||||
val bobParty = bob.info.legalIdentity
|
||||
val bobParty = bob.info.chooseIdentity()
|
||||
// Perform a protocol exchange to force the peer queue to be created
|
||||
alice.services.startFlow(SendFlow(bobParty, 0)).resultFuture.getOrThrow()
|
||||
return bobParty
|
||||
|
@ -22,6 +22,7 @@ import net.corda.node.utilities.ServiceIdentityGenerator
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.node.NodeBasedTest
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import java.util.*
|
||||
import java.util.concurrent.CountDownLatch
|
||||
@ -68,25 +69,25 @@ class P2PMessagingTest : NodeBasedTest() {
|
||||
RaftValidatingNotaryService.type.id,
|
||||
DISTRIBUTED_SERVICE_NAME)
|
||||
|
||||
val distributedService = ServiceInfo(RaftValidatingNotaryService.type, DISTRIBUTED_SERVICE_NAME)
|
||||
val notaryClusterAddress = freeLocalHostAndPort()
|
||||
startNetworkMapNode(
|
||||
DUMMY_MAP.name,
|
||||
advertisedServices = setOf(distributedService),
|
||||
advertisedServices = setOf(ServiceInfo(RaftValidatingNotaryService.type, DUMMY_MAP.name.copy(commonName = "DistributedService"))),
|
||||
configOverrides = mapOf("notaryNodeAddress" to notaryClusterAddress.toString()))
|
||||
val (serviceNode2, alice) = listOf(
|
||||
startNode(
|
||||
SERVICE_2_NAME,
|
||||
advertisedServices = setOf(distributedService),
|
||||
advertisedServices = setOf(ServiceInfo(RaftValidatingNotaryService.type, SERVICE_2_NAME.copy(commonName = "DistributedService"))),
|
||||
configOverrides = mapOf(
|
||||
"notaryNodeAddress" to freeLocalHostAndPort().toString(),
|
||||
"notaryClusterAddresses" to listOf(notaryClusterAddress.toString()))),
|
||||
startNode(ALICE.name)
|
||||
).transpose().getOrThrow()
|
||||
|
||||
assertAllNodesAreUsed(listOf(networkMapNode, serviceNode2), DISTRIBUTED_SERVICE_NAME, alice)
|
||||
assertAllNodesAreUsed(listOf(networkMapNode, serviceNode2), SERVICE_2_NAME.copy(commonName = "DistributedService"), alice)
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
fun `communicating with a distributed service which we're part of`() {
|
||||
val distributedService = startNotaryCluster(DISTRIBUTED_SERVICE_NAME, 2).getOrThrow()
|
||||
@ -182,7 +183,7 @@ class P2PMessagingTest : NodeBasedTest() {
|
||||
)
|
||||
|
||||
distributedServiceNodes.forEach {
|
||||
val nodeName = it.info.legalIdentity.name
|
||||
val nodeName = it.info.chooseIdentity().name
|
||||
it.network.addMessageHandler(dummyTopic) { netMessage, _ ->
|
||||
crashingNodes.requestsReceived.incrementAndGet()
|
||||
crashingNodes.firstRequestReceived.countDown()
|
||||
|
@ -5,7 +5,6 @@ import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.crypto.random63BitValue
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.utilities.NonEmptySet
|
||||
import net.corda.core.internal.cert
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.seconds
|
||||
@ -44,7 +43,7 @@ class P2PSecurityTest : NodeBasedTest() {
|
||||
|
||||
@Test
|
||||
fun `register with the network map service using a legal name different from the TLS CN`() {
|
||||
startSimpleNode(DUMMY_BANK_A.name, DUMMY_CA.certificate.cert).use {
|
||||
startSimpleNode(DUMMY_BANK_A.name, DEV_TRUST_ROOT.cert).use {
|
||||
// Register with the network map using a different legal name
|
||||
val response = it.registerWithNetworkMap(DUMMY_BANK_B.name)
|
||||
// We don't expect a response because the network map's host verification will prevent a connection back
|
||||
@ -60,7 +59,7 @@ class P2PSecurityTest : NodeBasedTest() {
|
||||
val config = testNodeConfiguration(
|
||||
baseDirectory = baseDirectory(legalName),
|
||||
myLegalName = legalName).also {
|
||||
whenever(it.networkMapService).thenReturn(NetworkMapInfo(networkMapNode.internals.configuration.p2pAddress, networkMapNode.info.legalIdentity.name))
|
||||
whenever(it.networkMapService).thenReturn(NetworkMapInfo(networkMapNode.internals.configuration.p2pAddress, networkMapNode.info.chooseIdentity().name))
|
||||
}
|
||||
config.configureWithDevSSLCertificate() // This creates the node's TLS cert with the CN as the legal name
|
||||
return SimpleNode(config, trustRoot = trustRoot).apply { start() }
|
||||
@ -68,7 +67,7 @@ class P2PSecurityTest : NodeBasedTest() {
|
||||
|
||||
private fun SimpleNode.registerWithNetworkMap(registrationName: CordaX500Name): CordaFuture<NetworkMapService.RegistrationResponse> {
|
||||
val legalIdentity = getTestPartyAndCertificate(registrationName, identity.public)
|
||||
val nodeInfo = NodeInfo(listOf(MOCK_HOST_AND_PORT), legalIdentity, NonEmptySet.of(legalIdentity), 1, serial = 1)
|
||||
val nodeInfo = NodeInfo(listOf(MOCK_HOST_AND_PORT), listOf(legalIdentity), 1, serial = 1)
|
||||
val registration = NodeRegistration(nodeInfo, System.currentTimeMillis(), AddOrRemove.ADD, Instant.MAX)
|
||||
val request = RegistrationRequest(registration.toWire(keyService, identity.public), network.myAddress)
|
||||
return network.sendRequest<NetworkMapService.RegistrationResponse>(NetworkMapService.REGISTER_TOPIC, request, networkMapNode.network.myAddress)
|
||||
|
@ -22,6 +22,7 @@ import net.corda.node.services.FlowPermissions
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.driver.driver
|
||||
import org.junit.Test
|
||||
import java.lang.management.ManagementFactory
|
||||
@ -40,7 +41,7 @@ class NodeStatePersistenceTests {
|
||||
|
||||
startNode(providedName = DUMMY_NOTARY.name, advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type))).getOrThrow()
|
||||
var nodeHandle = startNode(rpcUsers = listOf(user)).getOrThrow()
|
||||
val nodeName = nodeHandle.nodeInfo.legalIdentity.name
|
||||
val nodeName = nodeHandle.nodeInfo.chooseIdentity().name
|
||||
nodeHandle.rpcClientToNode().start(user.username, user.password).use {
|
||||
it.proxy.startFlow(::SendMessageFlow, message).returnValue.getOrThrow()
|
||||
}
|
||||
@ -139,7 +140,7 @@ class SendMessageFlow(private val message: Message) : FlowLogic<SignedTransactio
|
||||
|
||||
progressTracker.currentStep = GENERATING_TRANSACTION
|
||||
|
||||
val messageState = MessageState(message = message, by = serviceHub.myInfo.legalIdentity)
|
||||
val messageState = MessageState(message = message, by = serviceHub.myInfo.chooseIdentity())
|
||||
val txCommand = Command(MessageContract.Commands.Send(), messageState.participants.map { it.owningKey })
|
||||
val txBuilder = TransactionBuilder(notary).withItems(StateAndContract(messageState, MESSAGE_CONTRACT_PROGRAM_ID), txCommand)
|
||||
|
||||
|
@ -133,6 +133,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
|
||||
protected val services: ServiceHubInternal get() = _services
|
||||
private lateinit var _services: ServiceHubInternalImpl
|
||||
lateinit var legalIdentity: PartyAndCertificate
|
||||
protected lateinit var info: NodeInfo
|
||||
protected lateinit var checkpointStorage: CheckpointStorage
|
||||
protected lateinit var smm: StateMachineManager
|
||||
@ -380,7 +381,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
_services = ServiceHubInternalImpl()
|
||||
attachments = NodeAttachmentService(services.monitoringService.metrics)
|
||||
cordappProvider = CordappProvider(attachments, makeCordappLoader())
|
||||
val legalIdentity = obtainIdentity()
|
||||
legalIdentity = obtainIdentity()
|
||||
network = makeMessagingService(legalIdentity)
|
||||
info = makeInfo(legalIdentity)
|
||||
|
||||
@ -410,9 +411,10 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
|
||||
private fun makeInfo(legalIdentity: PartyAndCertificate): NodeInfo {
|
||||
val advertisedServiceEntries = makeServiceEntries()
|
||||
val allIdentities = advertisedServiceEntries.map { it.identity }.toSet() // TODO Add node's legalIdentity (after services removal).
|
||||
val allIdentitiesList = mutableListOf(legalIdentity)
|
||||
allIdentitiesList.addAll(advertisedServiceEntries.map { it.identity }) // TODO Will we keep service identities here, for example notaries?
|
||||
val addresses = myAddresses() // TODO There is no support for multiple IP addresses yet.
|
||||
return NodeInfo(addresses, legalIdentity, allIdentities, platformVersion, advertisedServiceEntries, platformClock.instant().toEpochMilli())
|
||||
return NodeInfo(addresses, allIdentitiesList, platformVersion, advertisedServiceEntries, platformClock.instant().toEpochMilli())
|
||||
}
|
||||
|
||||
/**
|
||||
@ -520,7 +522,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
"Initial network map address must indicate a node that provides a network map service"
|
||||
}
|
||||
val address: SingleMessageRecipient = networkMapAddress ?:
|
||||
network.getAddressOfParty(PartyInfo.Node(info)) as SingleMessageRecipient
|
||||
network.getAddressOfParty(PartyInfo.SingleNode(services.myInfo.legalIdentitiesAndCerts.first().party, info.addresses)) as SingleMessageRecipient
|
||||
// Register for updates, even if we're the one running the network map.
|
||||
return sendNetworkMapRegistration(address).flatMap { (error) ->
|
||||
check(error == null) { "Unable to register with the network map service: $error" }
|
||||
@ -534,7 +536,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
val instant = platformClock.instant()
|
||||
val expires = instant + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
|
||||
val reg = NodeRegistration(info, info.serial, ADD, expires)
|
||||
val request = RegistrationRequest(reg.toWire(services.keyManagementService, info.legalIdentityAndCert.owningKey), network.myAddress)
|
||||
val request = RegistrationRequest(reg.toWire(services.keyManagementService, info.legalIdentitiesAndCerts.first().owningKey), network.myAddress)
|
||||
return network.sendRequest(NetworkMapService.REGISTER_TOPIC, request, networkMapAddress)
|
||||
}
|
||||
|
||||
@ -577,12 +579,14 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
val caCertificates: Array<X509Certificate> = listOf(legalIdentity.certificate, clientCa?.certificate?.cert)
|
||||
.filterNotNull()
|
||||
.toTypedArray()
|
||||
val service = PersistentIdentityService(setOf(info.legalIdentityAndCert), trustRoot = trustRoot, caCertificates = *caCertificates)
|
||||
services.networkMapCache.partyNodes.forEach { service.verifyAndRegisterIdentity(it.legalIdentityAndCert) }
|
||||
val service = PersistentIdentityService(info.legalIdentitiesAndCerts.toSet(), trustRoot = trustRoot, caCertificates = *caCertificates)
|
||||
services.networkMapCache.partyNodes.forEach { it.legalIdentitiesAndCerts.forEach { service.verifyAndRegisterIdentity(it) } }
|
||||
services.networkMapCache.changed.subscribe { mapChange ->
|
||||
// TODO how should we handle network map removal
|
||||
if (mapChange is MapChange.Added) {
|
||||
service.verifyAndRegisterIdentity(mapChange.node.legalIdentityAndCert)
|
||||
mapChange.node.legalIdentitiesAndCerts.forEach {
|
||||
service.verifyAndRegisterIdentity(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
return service
|
||||
@ -712,7 +716,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
makeIdentityService(
|
||||
trustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA),
|
||||
caKeyStore.certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA),
|
||||
info.legalIdentityAndCert)
|
||||
legalIdentity)
|
||||
}
|
||||
override val attachments: AttachmentStorage get() = this@AbstractNode.attachments
|
||||
override val networkService: MessagingService get() = network
|
||||
@ -726,8 +730,9 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
return cordappServices.getInstance(type) ?: throw IllegalArgumentException("Corda service ${type.name} does not exist")
|
||||
}
|
||||
|
||||
override fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator): FlowStateMachineImpl<T> {
|
||||
return serverThread.fetchFrom { smm.add(logic, flowInitiator) }
|
||||
override fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate?): FlowStateMachineImpl<T> {
|
||||
check(me == null || me in myInfo.legalIdentitiesAndCerts) { "Attempt to start a flow with legal identity not belonging to this node." }
|
||||
return serverThread.fetchFrom { smm.add(logic, flowInitiator, me) }
|
||||
}
|
||||
|
||||
override fun getFlowFactory(initiatingFlowClass: Class<out FlowLogic<*>>): InitiatedFlowFactory<*>? {
|
||||
|
@ -10,6 +10,7 @@ import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.messaging.*
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.NetworkMapCache
|
||||
@ -110,7 +111,7 @@ class CordaRPCOpsImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun nodeIdentity(): NodeInfo {
|
||||
override fun nodeInfo(): NodeInfo {
|
||||
return services.myInfo
|
||||
}
|
||||
|
||||
@ -142,10 +143,11 @@ class CordaRPCOpsImpl(
|
||||
|
||||
private fun <T> startFlow(logicType: Class<out FlowLogic<T>>, args: Array<out Any?>): FlowStateMachineImpl<T> {
|
||||
require(logicType.isAnnotationPresent(StartableByRPC::class.java)) { "${logicType.name} was not designed for RPC" }
|
||||
val me = services.myInfo.legalIdentitiesAndCerts.first() // TODO RPC flows should have mapping user -> identity that should be resolved automatically on starting flow.
|
||||
val rpcContext = getRpcContext()
|
||||
rpcContext.requirePermission(startFlowPermission(logicType))
|
||||
val currentUser = FlowInitiator.RPC(rpcContext.currentUser.username)
|
||||
return services.invokeFlowAsync(logicType, currentUser, *args)
|
||||
return services.invokeFlowAsync(logicType, currentUser, me, *args)
|
||||
}
|
||||
|
||||
override fun attachmentExists(id: SecureHash): Boolean {
|
||||
|
@ -96,7 +96,7 @@ open class NodeStartup(val args: Array<String>) {
|
||||
printPluginsAndServices(node.internals)
|
||||
node.internals.nodeReadyFuture.thenMatch({
|
||||
val elapsed = (System.currentTimeMillis() - startTime) / 10 / 100.0
|
||||
val name = node.info.legalIdentity.name.organisation
|
||||
val name = node.info.legalIdentitiesAndCerts.first().name.organisation
|
||||
Node.printBasicNodeInfo("Node for \"$name\" started up and registered in $elapsed sec")
|
||||
|
||||
// Don't start the shell if there's no console attached.
|
||||
|
@ -57,7 +57,7 @@ class SwapIdentitiesHandler(val otherSide: Party, val revocationEnabled: Boolean
|
||||
override fun call(): Unit {
|
||||
val revocationEnabled = false
|
||||
progressTracker.currentStep = SENDING_KEY
|
||||
val legalIdentityAnonymous = serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.legalIdentityAndCert, revocationEnabled)
|
||||
val legalIdentityAnonymous = serviceHub.keyManagementService.freshKeyAndCert(ourIdentity, revocationEnabled)
|
||||
sendAndReceive<PartyAndCertificate>(otherSide, legalIdentityAnonymous).unwrap { confidentialIdentity ->
|
||||
SwapIdentitiesFlow.validateAndRegisterIdentity(serviceHub.identityService, otherSide, confidentialIdentity)
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.flows.FlowInitiator
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.StateMachineRunId
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.internal.FlowStateMachine
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import net.corda.core.messaging.DataFeed
|
||||
@ -29,9 +31,9 @@ interface NetworkMapCacheInternal : NetworkMapCache {
|
||||
/**
|
||||
* Deregister from updates from the given map service.
|
||||
* @param network the network messaging service.
|
||||
* @param service the network map service to fetch current state from.
|
||||
* @param mapParty the network map service party to fetch current state from.
|
||||
*/
|
||||
fun deregisterForUpdates(network: MessagingService, service: NodeInfo): CordaFuture<Unit>
|
||||
fun deregisterForUpdates(network: MessagingService, mapParty: Party): CordaFuture<Unit>
|
||||
|
||||
/**
|
||||
* Add a network map service; fetches a copy of the latest map from the service and subscribes to any further
|
||||
@ -116,7 +118,7 @@ interface ServiceHubInternal : ServiceHub {
|
||||
* Starts an already constructed flow. Note that you must be on the server thread to call this method.
|
||||
* @param flowInitiator indicates who started the flow, see: [FlowInitiator].
|
||||
*/
|
||||
fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator): FlowStateMachineImpl<T>
|
||||
fun <T> startFlow(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate? = null): FlowStateMachineImpl<T>
|
||||
|
||||
/**
|
||||
* Will check [logicType] and [args] against a whitelist and if acceptable then construct and initiate the flow.
|
||||
@ -129,11 +131,12 @@ interface ServiceHubInternal : ServiceHub {
|
||||
fun <T> invokeFlowAsync(
|
||||
logicType: Class<out FlowLogic<T>>,
|
||||
flowInitiator: FlowInitiator,
|
||||
me: PartyAndCertificate? = null,
|
||||
vararg args: Any?): FlowStateMachineImpl<T> {
|
||||
val logicRef = FlowLogicRefFactoryImpl.createForRPC(logicType, *args)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val logic = FlowLogicRefFactoryImpl.toFlowLogic(logicRef) as FlowLogic<T>
|
||||
return startFlow(logic, flowInitiator)
|
||||
return startFlow(logic, flowInitiator, me)
|
||||
}
|
||||
|
||||
fun getFlowFactory(initiatingFlowClass: Class<out FlowLogic<*>>): InitiatedFlowFactory<*>?
|
||||
|
@ -5,6 +5,7 @@ import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.toStringShort
|
||||
import net.corda.core.identity.*
|
||||
import net.corda.core.internal.cert
|
||||
import net.corda.core.internal.toX509CertHolder
|
||||
import net.corda.core.node.services.IdentityService
|
||||
import net.corda.core.node.services.UnknownAnonymousPartyException
|
||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
@ -112,7 +113,16 @@ class PersistentIdentityService(identities: Iterable<PartyAndCertificate> = empt
|
||||
@Throws(CertificateExpiredException::class, CertificateNotYetValidException::class, InvalidAlgorithmParameterException::class)
|
||||
override fun verifyAndRegisterIdentity(identity: PartyAndCertificate): PartyAndCertificate? {
|
||||
// Validate the chain first, before we do anything clever with it
|
||||
identity.verify(trustAnchor)
|
||||
try {
|
||||
identity.verify(trustAnchor)
|
||||
} catch (e: CertPathValidatorException) {
|
||||
log.error(e.localizedMessage)
|
||||
log.error("Path = ")
|
||||
identity.certPath.certificates.reversed().forEach {
|
||||
log.error(it.toX509CertHolder().subject.toString())
|
||||
}
|
||||
throw e
|
||||
}
|
||||
|
||||
log.info("Registering identity $identity")
|
||||
val key = mapToKey(identity)
|
||||
|
@ -131,7 +131,7 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
|
||||
if (!running) {
|
||||
configureAndStartServer()
|
||||
// Deploy bridge to the network map service
|
||||
config.networkMapService?.let { deployBridge(NetworkMapAddress(it.address), it.legalName) }
|
||||
config.networkMapService?.let { deployBridge(NetworkMapAddress(it.address), setOf(it.legalName)) }
|
||||
networkChangeHandle = networkMapCache.changed.subscribe { updateBridgesOnNetworkChange(it) }
|
||||
running = true
|
||||
}
|
||||
@ -295,36 +295,24 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
|
||||
|
||||
private fun deployBridgesFromNewQueue(queueName: String) {
|
||||
log.debug { "Queue created: $queueName, deploying bridge(s)" }
|
||||
|
||||
fun deployBridgeToPeer(nodeInfo: NodeInfo) {
|
||||
log.debug("Deploying bridge for $queueName to $nodeInfo")
|
||||
val address = nodeInfo.addresses.first() // TODO Load balancing.
|
||||
deployBridge(queueName, address, nodeInfo.legalIdentity.name)
|
||||
val address = nodeInfo.addresses.first()
|
||||
deployBridge(queueName, address, nodeInfo.legalIdentitiesAndCerts.map { it.name }.toSet())
|
||||
}
|
||||
|
||||
when {
|
||||
queueName.startsWith(PEERS_PREFIX) -> try {
|
||||
if (queueName.startsWith(PEERS_PREFIX)) {
|
||||
try {
|
||||
val identity = parsePublicKeyBase58(queueName.substring(PEERS_PREFIX.length))
|
||||
val nodeInfo = networkMapCache.getNodeByLegalIdentityKey(identity)
|
||||
if (nodeInfo != null) {
|
||||
deployBridgeToPeer(nodeInfo)
|
||||
val nodeInfos = networkMapCache.getNodesByLegalIdentityKey(identity)
|
||||
if (nodeInfos.isNotEmpty()) {
|
||||
nodeInfos.forEach { deployBridgeToPeer(it) }
|
||||
} else {
|
||||
log.error("Queue created for a peer that we don't know from the network map: $queueName")
|
||||
}
|
||||
} catch (e: AddressFormatException) {
|
||||
log.error("Flow violation: Could not parse peer queue name as Base 58: $queueName")
|
||||
}
|
||||
|
||||
queueName.startsWith(SERVICES_PREFIX) -> try {
|
||||
val identity = parsePublicKeyBase58(queueName.substring(SERVICES_PREFIX.length))
|
||||
val nodeInfos = networkMapCache.getNodesByAdvertisedServiceIdentityKey(identity)
|
||||
// Create a bridge for each node advertising the service.
|
||||
for (nodeInfo in nodeInfos) {
|
||||
deployBridgeToPeer(nodeInfo)
|
||||
}
|
||||
} catch (e: AddressFormatException) {
|
||||
log.error("Flow violation: Could not parse service queue name as Base 58: $queueName")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,16 +327,14 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
|
||||
private fun updateBridgesOnNetworkChange(change: MapChange) {
|
||||
log.debug { "Updating bridges on network map change: ${change.node}" }
|
||||
fun gatherAddresses(node: NodeInfo): Sequence<ArtemisPeerAddress> {
|
||||
val peerAddress = getArtemisPeerAddress(node)
|
||||
val addresses = mutableListOf(peerAddress)
|
||||
node.advertisedServices.mapTo(addresses) { NodeAddress.asService(it.identity.owningKey, peerAddress.hostAndPort) }
|
||||
return addresses.asSequence()
|
||||
val address = node.addresses.first()
|
||||
return node.legalIdentitiesAndCerts.map { getArtemisPeerAddress(it.party, address, config.networkMapService?.legalName) }.asSequence()
|
||||
}
|
||||
|
||||
fun deployBridges(node: NodeInfo) {
|
||||
gatherAddresses(node)
|
||||
.filter { queueExists(it.queueName) && !bridgeExists(it.bridgeName) }
|
||||
.forEach { deployBridge(it, node.legalIdentity.name) }
|
||||
.forEach { deployBridge(it, node.legalIdentitiesAndCerts.map { it.name }.toSet()) }
|
||||
}
|
||||
|
||||
fun destroyBridges(node: NodeInfo) {
|
||||
@ -372,8 +358,8 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
|
||||
}
|
||||
}
|
||||
|
||||
private fun deployBridge(address: ArtemisPeerAddress, legalName: CordaX500Name) {
|
||||
deployBridge(address.queueName, address.hostAndPort, legalName)
|
||||
private fun deployBridge(address: ArtemisPeerAddress, legalNames: Set<CordaX500Name>) {
|
||||
deployBridge(address.queueName, address.hostAndPort, legalNames)
|
||||
}
|
||||
|
||||
private fun createTcpTransport(connectionDirection: ConnectionDirection, host: String, port: Int, enableSSL: Boolean = true) =
|
||||
@ -385,10 +371,10 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
|
||||
* as defined by ArtemisAddress.queueName. A bridge is then created to forward messages from this queue to the node's
|
||||
* P2P address.
|
||||
*/
|
||||
private fun deployBridge(queueName: String, target: NetworkHostAndPort, legalName: CordaX500Name) {
|
||||
private fun deployBridge(queueName: String, target: NetworkHostAndPort, legalNames: Set<CordaX500Name>) {
|
||||
val connectionDirection = ConnectionDirection.Outbound(
|
||||
connectorFactoryClassName = VerifyingNettyConnectorFactory::class.java.name,
|
||||
expectedCommonName = legalName
|
||||
expectedCommonNames = legalNames
|
||||
)
|
||||
val tcpTransport = createTcpTransport(connectionDirection, target.host, target.port)
|
||||
tcpTransport.params[ArtemisMessagingServer::class.java.name] = this
|
||||
@ -424,9 +410,9 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
|
||||
private fun getBridgeName(queueName: String, hostAndPort: NetworkHostAndPort): String = "$queueName -> $hostAndPort"
|
||||
|
||||
// This is called on one of Artemis' background threads
|
||||
internal fun hostVerificationFail(expectedLegalName: CordaX500Name, errorMsg: String?) {
|
||||
internal fun hostVerificationFail(expectedLegalNames: Set<CordaX500Name>, errorMsg: String?) {
|
||||
log.error(errorMsg)
|
||||
if (expectedLegalName == config.networkMapService?.legalName) {
|
||||
if (config.networkMapService?.legalName in expectedLegalNames) {
|
||||
// If the peer that failed host verification was the network map node then we're in big trouble and need to bail!
|
||||
_networkMapConnectionFuture!!.setException(IOException("${config.networkMapService} failed host verification check"))
|
||||
}
|
||||
@ -492,7 +478,8 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>,
|
||||
override fun createConnection(): Connection? {
|
||||
val connection = super.createConnection() as? NettyConnection
|
||||
if (sslEnabled && connection != null) {
|
||||
val expectedLegalName = configuration[ArtemisTcpTransport.VERIFY_PEER_LEGAL_NAME] as CordaX500Name
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val expectedLegalNames = (configuration[ArtemisTcpTransport.VERIFY_PEER_LEGAL_NAME] ?: emptySet<CordaX500Name>()) as Set<CordaX500Name>
|
||||
try {
|
||||
val session = connection.channel
|
||||
.pipeline()
|
||||
@ -500,22 +487,27 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>,
|
||||
.engine()
|
||||
.session
|
||||
// Checks the peer name is the one we are expecting.
|
||||
// TODO Some problems here: after introduction of multiple legal identities on the node and removal of the main one,
|
||||
// we run into the issue, who are we connecting to. There are some solutions to that: advertise `network identity`;
|
||||
// have mapping port -> identity (but, design doc says about removing SingleMessageRecipient and having just NetworkHostAndPort,
|
||||
// it was convenient to store that this way); SNI.
|
||||
val peerLegalName = CordaX500Name.parse(session.peerPrincipal.name)
|
||||
require(peerLegalName == expectedLegalName) {
|
||||
"Peer has wrong CN - expected $expectedLegalName but got $peerLegalName. This is either a fatal " +
|
||||
val expectedLegalName = expectedLegalNames.singleOrNull { it == peerLegalName }
|
||||
require(expectedLegalName != null) {
|
||||
"Peer has wrong CN - expected $expectedLegalNames but got $peerLegalName. This is either a fatal " +
|
||||
"misconfiguration by the remote peer or an SSL man-in-the-middle attack!"
|
||||
}
|
||||
// Make sure certificate has the same name.
|
||||
val peerCertificateName = CordaX500Name.build(X500Principal(session.peerCertificateChain[0].subjectDN.name))
|
||||
require(peerCertificateName == expectedLegalName) {
|
||||
"Peer has wrong subject name in the certificate - expected $expectedLegalName but got $peerCertificateName. This is either a fatal " +
|
||||
"Peer has wrong subject name in the certificate - expected $expectedLegalNames but got $peerCertificateName. This is either a fatal " +
|
||||
"misconfiguration by the remote peer or an SSL man-in-the-middle attack!"
|
||||
}
|
||||
X509Utilities.validateCertificateChain(session.localCertificates.last() as java.security.cert.X509Certificate, *session.peerCertificates)
|
||||
server.onTcpConnection(peerLegalName)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
connection.close()
|
||||
server.hostVerificationFail(expectedLegalName, e.message)
|
||||
server.hostVerificationFail(expectedLegalNames, e.message)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ class NodeMessagingClient(override val config: NodeConfiguration,
|
||||
* Apart from the NetworkMapService this is the only other address accessible to the node outside of lookups against the NetworkMapCache.
|
||||
*/
|
||||
override val myAddress: SingleMessageRecipient = if (myIdentity != null) {
|
||||
NodeAddress.asPeer(myIdentity, advertisedAddress)
|
||||
NodeAddress.asSingleNode(myIdentity, advertisedAddress)
|
||||
} else {
|
||||
NetworkMapAddress(advertisedAddress)
|
||||
}
|
||||
@ -622,10 +622,13 @@ class NodeMessagingClient(override val config: NodeConfiguration,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Rethink PartyInfo idea and merging PeerAddress/ServiceAddress (the only difference is that Service address doesn't hold host and port)
|
||||
override fun getAddressOfParty(partyInfo: PartyInfo): MessageRecipients {
|
||||
return when (partyInfo) {
|
||||
is PartyInfo.Node -> getArtemisPeerAddress(partyInfo.node)
|
||||
is PartyInfo.Service -> ServiceAddress(partyInfo.service.identity.owningKey)
|
||||
is PartyInfo.SingleNode -> {
|
||||
getArtemisPeerAddress(partyInfo.party, partyInfo.addresses.first(), config.networkMapService?.legalName)
|
||||
}
|
||||
is PartyInfo.DistributedNode -> ServiceAddress(partyInfo.party.owningKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -251,8 +251,10 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal,
|
||||
logger.error(msg, e)
|
||||
return RegistrationResponse(msg)
|
||||
}
|
||||
|
||||
val node = change.node
|
||||
// Get identity from signature on node's registration and use it as an index.
|
||||
val identity = node.legalIdentitiesAndCerts.singleOrNull { request.wireReg.sig.by == it.owningKey }
|
||||
identity ?: return RegistrationResponse("Key from signature on the node registration wasn't found in NodeInfo")
|
||||
|
||||
if (node.platformVersion < minimumPlatformVersion) {
|
||||
return RegistrationResponse("Minimum platform version requirement not met: $minimumPlatformVersion")
|
||||
@ -262,7 +264,7 @@ abstract class AbstractNetworkMapService(services: ServiceHubInternal,
|
||||
// in on different threads, there is no risk of a race condition while checking
|
||||
// sequence numbers.
|
||||
val registrationInfo = try {
|
||||
nodeRegistrations.compute(node.legalIdentityAndCert) { _, existing: NodeRegistrationInfo? ->
|
||||
nodeRegistrations.compute(identity) { _, existing: NodeRegistrationInfo? ->
|
||||
require(!((existing == null || existing.reg.type == REMOVE) && change.type == REMOVE)) {
|
||||
"Attempting to de-register unknown node"
|
||||
}
|
||||
@ -352,7 +354,9 @@ data class NodeRegistration(val node: NodeInfo, val serial: Long, val type: AddO
|
||||
class WireNodeRegistration(raw: SerializedBytes<NodeRegistration>, sig: DigitalSignature.WithKey) : SignedData<NodeRegistration>(raw, sig) {
|
||||
@Throws(IllegalArgumentException::class)
|
||||
override fun verifyData(data: NodeRegistration) {
|
||||
require(data.node.legalIdentity.owningKey.isFulfilledBy(sig.by))
|
||||
// Check that the registration is fulfilled by any of node's identities.
|
||||
// TODO It may cause some problems with distributed services? We loose node's main identity. Should be all signatures instead of isFulfilledBy?
|
||||
require(data.node.legalIdentitiesAndCerts.any { it.owningKey.isFulfilledBy(sig.by) })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,8 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
private var registeredForPush = false
|
||||
// TODO Small explanation, partyNodes and registeredNodes is left in memory as it was before, because it will be removed in
|
||||
// next PR that gets rid of services. These maps are used only for queries by service.
|
||||
override val partyNodes: List<NodeInfo> get() = registeredNodes.map { it.value }
|
||||
protected val registeredNodes: MutableMap<PublicKey, NodeInfo> = Collections.synchronizedMap(HashMap())
|
||||
override val partyNodes: MutableList<NodeInfo> get() = registeredNodes.map { it.value }.toMutableList()
|
||||
override val networkMapNodes: List<NodeInfo> get() = getNodesWithService(NetworkMapService.type)
|
||||
private val _changed = PublishSubject.create<MapChange>()
|
||||
// We use assignment here so that multiple subscribers share the same wrapped Observable.
|
||||
@ -66,7 +67,6 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
|
||||
private val _registrationFuture = openFuture<Void?>()
|
||||
override val nodeReady: CordaFuture<Void?> get() = _registrationFuture
|
||||
protected val registeredNodes: MutableMap<PublicKey, NodeInfo> = Collections.synchronizedMap(HashMap())
|
||||
private var _loadDBSuccess: Boolean = false
|
||||
override val loadDBSuccess get() = _loadDBSuccess
|
||||
|
||||
@ -76,13 +76,13 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
|
||||
override fun getPartyInfo(party: Party): PartyInfo? {
|
||||
val nodes = serviceHub.database.transaction { queryByIdentityKey(party.owningKey) }
|
||||
if (nodes.size == 1 && nodes[0].legalIdentity == party) {
|
||||
return PartyInfo.Node(nodes[0])
|
||||
if (nodes.size == 1 && party in nodes[0].legalIdentities) {
|
||||
return PartyInfo.SingleNode(party, nodes[0].addresses)
|
||||
}
|
||||
for (node in nodes) {
|
||||
for (service in node.advertisedServices) {
|
||||
if (service.identity.party == party) {
|
||||
return PartyInfo.Service(service)
|
||||
return PartyInfo.DistributedNode(party)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -90,14 +90,14 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
}
|
||||
|
||||
// TODO See comment to queryByLegalName why it's left like that.
|
||||
override fun getNodeByLegalName(principal: CordaX500Name): NodeInfo? = partyNodes.singleOrNull { it.legalIdentity.name == principal }
|
||||
override fun getNodeByLegalName(principal: CordaX500Name): NodeInfo? = partyNodes.singleOrNull { principal in it.legalIdentities.map { it.name } }
|
||||
//serviceHub!!.database.transaction { queryByLegalName(principal).firstOrNull() }
|
||||
override fun getNodeByLegalIdentityKey(identityKey: PublicKey): NodeInfo? =
|
||||
serviceHub.database.transaction { queryByIdentityKey(identityKey).firstOrNull() }
|
||||
override fun getNodesByLegalIdentityKey(identityKey: PublicKey): List<NodeInfo> =
|
||||
serviceHub.database.transaction { queryByIdentityKey(identityKey) }
|
||||
override fun getNodeByLegalIdentity(party: AbstractParty): NodeInfo? {
|
||||
val wellKnownParty = serviceHub.identityService.partyFromAnonymous(party)
|
||||
return wellKnownParty?.let {
|
||||
getNodeByLegalIdentityKey(it.owningKey)
|
||||
getNodesByLegalIdentityKey(it.owningKey).singleOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
|
||||
override fun addNode(node: NodeInfo) {
|
||||
synchronized(_changed) {
|
||||
val previousNode = registeredNodes.put(node.legalIdentity.owningKey, node)
|
||||
val previousNode = registeredNodes.put(node.legalIdentities.first().owningKey, node) // TODO hack... we left the first one as special one
|
||||
if (previousNode == null) {
|
||||
serviceHub.database.transaction {
|
||||
updateInfoDB(node)
|
||||
@ -160,7 +160,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
|
||||
override fun removeNode(node: NodeInfo) {
|
||||
synchronized(_changed) {
|
||||
registeredNodes.remove(node.legalIdentity.owningKey)
|
||||
registeredNodes.remove(node.legalIdentities.first().owningKey)
|
||||
serviceHub.database.transaction {
|
||||
removeInfoDB(node)
|
||||
changePublisher.onNext(MapChange.Removed(node))
|
||||
@ -170,13 +170,14 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
|
||||
/**
|
||||
* Unsubscribes from updates from the given map service.
|
||||
* @param service the network map service to listen to updates from.
|
||||
* @param mapParty the network map service party to listen to updates from.
|
||||
*/
|
||||
override fun deregisterForUpdates(network: MessagingService, service: NodeInfo): CordaFuture<Unit> {
|
||||
override fun deregisterForUpdates(network: MessagingService, mapParty: Party): CordaFuture<Unit> {
|
||||
// Fetch the network map and register for updates at the same time
|
||||
val req = NetworkMapService.SubscribeRequest(false, network.myAddress)
|
||||
// `network.getAddressOfParty(partyInfo)` is a work-around for MockNetwork and InMemoryMessaging to get rid of SingleMessageRecipient in NodeInfo.
|
||||
val address = network.getAddressOfParty(PartyInfo.Node(service))
|
||||
val address = getPartyInfo(mapParty)?.let{ network.getAddressOfParty(it) } ?:
|
||||
throw IllegalArgumentException("Can't deregister for updates, don't know the party: $mapParty")
|
||||
val future = network.sendRequest<SubscribeResponse>(NetworkMapService.SUBSCRIPTION_TOPIC, req, address).map {
|
||||
if (it.confirmed) Unit else throw NetworkCacheError.DeregistrationFailed()
|
||||
}
|
||||
@ -255,7 +256,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
session.use {
|
||||
val tx = session.beginTransaction()
|
||||
// TODO For now the main legal identity is left in NodeInfo, this should be set comparision/come up with index for NodeInfo?
|
||||
val info = findByIdentityKey(session, nodeInfo.legalIdentity.owningKey)
|
||||
val info = findByIdentityKey(session, nodeInfo.legalIdentitiesAndCerts.first().owningKey)
|
||||
val nodeInfoEntry = generateMappedObject(nodeInfo)
|
||||
if (info.isNotEmpty()) {
|
||||
nodeInfoEntry.id = info[0].id
|
||||
@ -268,7 +269,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
|
||||
private fun removeInfoDB(nodeInfo: NodeInfo) {
|
||||
createSession {
|
||||
val info = findByIdentityKey(it, nodeInfo.legalIdentity.owningKey).single()
|
||||
val info = findByIdentityKey(it, nodeInfo.legalIdentitiesAndCerts.first().owningKey).single()
|
||||
it.remove(info)
|
||||
}
|
||||
}
|
||||
@ -317,9 +318,9 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
||||
return NodeInfoSchemaV1.PersistentNodeInfo(
|
||||
id = 0,
|
||||
addresses = nodeInfo.addresses.map { NodeInfoSchemaV1.DBHostAndPort.fromHostAndPort(it) },
|
||||
legalIdentitiesAndCerts = nodeInfo.legalIdentitiesAndCerts.map { NodeInfoSchemaV1.DBPartyAndCertificate(it) }.toSet()
|
||||
// TODO It's workaround to keep the main identity, will be removed in future PR getting rid of services.
|
||||
+ NodeInfoSchemaV1.DBPartyAndCertificate(nodeInfo.legalIdentityAndCert, isMain = true),
|
||||
// TODO Another ugly hack with special first identity...
|
||||
legalIdentitiesAndCerts = nodeInfo.legalIdentitiesAndCerts.mapIndexed { idx, elem ->
|
||||
NodeInfoSchemaV1.DBPartyAndCertificate(elem, isMain = idx == 0) },
|
||||
platformVersion = nodeInfo.platformVersion,
|
||||
advertisedServices = nodeInfo.advertisedServices.map { NodeInfoSchemaV1.DBServiceEntry(it.serialize().bytes) },
|
||||
serial = nodeInfo.serial
|
||||
|
@ -11,6 +11,7 @@ import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.random63BitValue
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.internal.concurrent.OpenFuture
|
||||
import net.corda.core.internal.concurrent.openFuture
|
||||
@ -35,7 +36,8 @@ class FlowPermissionException(message: String) : FlowException(message)
|
||||
class FlowStateMachineImpl<R>(override val id: StateMachineRunId,
|
||||
val logic: FlowLogic<R>,
|
||||
scheduler: FiberScheduler,
|
||||
override val flowInitiator: FlowInitiator) : Fiber<Unit>(id.toString(), scheduler), FlowStateMachine<R> {
|
||||
override val flowInitiator: FlowInitiator,
|
||||
override val ourIdentity: PartyAndCertificate) : Fiber<Unit>(id.toString(), scheduler), FlowStateMachine<R> {
|
||||
companion object {
|
||||
// Used to work around a small limitation in Quasar.
|
||||
private val QUASAR_UNBLOCKER = Fiber::class.staticField<Any>("SERIALIZER_BLOCKER").value
|
||||
|
@ -3,6 +3,7 @@ package net.corda.node.services.statemachine
|
||||
import net.corda.core.flows.FlowException
|
||||
import net.corda.core.flows.UnexpectedFlowEndException
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.internal.castIfPossible
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.utilities.UntrustworthyData
|
||||
@ -25,7 +26,9 @@ data class SessionInit(val initiatorSessionId: Long,
|
||||
val initiatingFlowClass: String,
|
||||
val flowVersion: Int,
|
||||
val appName: String,
|
||||
val firstPayload: Any?) : SessionMessage
|
||||
val firstPayload: Any?,
|
||||
// Left as a placeholder for support of multiple identities on a node. For now we choose the first one as a special one.
|
||||
val otherIdentity: PartyAndCertificate? = null) : SessionMessage
|
||||
|
||||
data class SessionConfirm(override val initiatorSessionId: Long,
|
||||
val initiatedSessionId: Long,
|
||||
|
@ -14,6 +14,7 @@ import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.random63BitValue
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.internal.ThreadBox
|
||||
import net.corda.core.internal.bufferUntilSubscribed
|
||||
import net.corda.core.internal.castIfPossible
|
||||
@ -288,7 +289,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
|
||||
|
||||
private fun onSessionMessage(message: ReceivedMessage) {
|
||||
val sessionMessage = message.data.deserialize<SessionMessage>()
|
||||
val sender = serviceHub.networkMapCache.getNodeByLegalName(message.peer)?.legalIdentity
|
||||
val sender = serviceHub.networkMapCache.getPeerByLegalName(message.peer)
|
||||
if (sender != null) {
|
||||
when (sessionMessage) {
|
||||
is ExistingSessionMessage -> onExistingSessionMessage(sessionMessage, sender)
|
||||
@ -370,7 +371,8 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
|
||||
session.receivedMessages += ReceivedSessionMessage(sender, SessionData(session.ourSessionId, sessionInit.firstPayload))
|
||||
}
|
||||
openSessions[session.ourSessionId] = session
|
||||
val fiber = createFiber(flow, FlowInitiator.Peer(sender))
|
||||
val meIdentity = sessionInit.otherIdentity ?: serviceHub.myInfo.legalIdentitiesAndCerts.first()
|
||||
val fiber = createFiber(flow, FlowInitiator.Peer(sender), meIdentity)
|
||||
flowSession.sessionFlow = flow
|
||||
flowSession.stateMachine = fiber
|
||||
fiber.openSessions[Pair(flow, sender)] = session
|
||||
@ -425,9 +427,9 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> createFiber(logic: FlowLogic<T>, flowInitiator: FlowInitiator): FlowStateMachineImpl<T> {
|
||||
private fun <T> createFiber(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate): FlowStateMachineImpl<T> {
|
||||
val id = StateMachineRunId.createRandom()
|
||||
return FlowStateMachineImpl(id, logic, scheduler, flowInitiator).apply { initFiber(this) }
|
||||
return FlowStateMachineImpl(id, logic, scheduler, flowInitiator, me).apply { initFiber(this) }
|
||||
}
|
||||
|
||||
private fun initFiber(fiber: FlowStateMachineImpl<*>) {
|
||||
@ -512,11 +514,11 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
|
||||
*
|
||||
* Note that you must be on the [executor] thread.
|
||||
*/
|
||||
fun <T> add(logic: FlowLogic<T>, flowInitiator: FlowInitiator): FlowStateMachineImpl<T> {
|
||||
fun <T> add(logic: FlowLogic<T>, flowInitiator: FlowInitiator, me: PartyAndCertificate?): FlowStateMachineImpl<T> {
|
||||
// TODO: Check that logic has @Suspendable on its call method.
|
||||
executor.checkOnThread()
|
||||
val fiber = database.transaction {
|
||||
val fiber = createFiber(logic, flowInitiator)
|
||||
val fiber = createFiber(logic, flowInitiator, me ?: serviceHub.myInfo.legalIdentitiesAndCerts.first())
|
||||
updateCheckpoint(fiber)
|
||||
fiber
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ class CordappSmokeTest {
|
||||
|
||||
factory.create(aliceConfig).use { alice ->
|
||||
alice.connect().use { connectionToAlice ->
|
||||
val aliceIdentity = connectionToAlice.proxy.nodeIdentity().legalIdentity
|
||||
val aliceIdentity = connectionToAlice.proxy.nodeInfo().legalIdentitiesAndCerts.first().party
|
||||
val future = connectionToAlice.proxy.startFlow(::GatherContextsFlow, aliceIdentity).returnValue
|
||||
val (sessionInitContext, sessionConfirmContext) = future.getOrThrow()
|
||||
val selfCordappName = selfCordapp.fileName.toString().removeSuffix(".jar")
|
||||
|
@ -31,6 +31,7 @@ import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.PermissionException
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.expect
|
||||
import net.corda.testing.expectEvents
|
||||
import net.corda.testing.node.MockNetwork
|
||||
@ -100,7 +101,7 @@ class CordaRPCOpsImplTest {
|
||||
}
|
||||
|
||||
// Tell the monitoring service node to issue some cash
|
||||
val recipient = aliceNode.info.legalIdentity
|
||||
val recipient = aliceNode.info.chooseIdentity()
|
||||
val result = rpc.startFlow(::CashIssueFlow, Amount(quantity, GBP), ref, notaryNode.info.notaryIdentity)
|
||||
mockNet.runNetwork()
|
||||
|
||||
@ -119,7 +120,7 @@ class CordaRPCOpsImplTest {
|
||||
|
||||
val anonymisedRecipient = result.returnValue.getOrThrow().recipient!!
|
||||
val expectedState = Cash.State(Amount(quantity,
|
||||
Issued(aliceNode.info.legalIdentity.ref(ref), GBP)),
|
||||
Issued(aliceNode.info.chooseIdentity().ref(ref), GBP)),
|
||||
anonymisedRecipient)
|
||||
|
||||
// Query vault via RPC
|
||||
@ -150,7 +151,7 @@ class CordaRPCOpsImplTest {
|
||||
|
||||
mockNet.runNetwork()
|
||||
|
||||
rpc.startFlow(::CashPaymentFlow, 100.DOLLARS, aliceNode.info.legalIdentity)
|
||||
rpc.startFlow(::CashPaymentFlow, 100.DOLLARS, aliceNode.info.chooseIdentity())
|
||||
|
||||
mockNet.runNetwork()
|
||||
|
||||
@ -184,7 +185,7 @@ class CordaRPCOpsImplTest {
|
||||
require(stx.tx.outputs.size == 1)
|
||||
val signaturePubKeys = stx.sigs.map { it.by }.toSet()
|
||||
// Only Alice signed, as issuer
|
||||
val aliceKey = aliceNode.info.legalIdentity.owningKey
|
||||
val aliceKey = aliceNode.info.chooseIdentity().owningKey
|
||||
require(signaturePubKeys.size <= aliceKey.keys.size)
|
||||
require(aliceKey.isFulfilledBy(signaturePubKeys))
|
||||
},
|
||||
|
@ -7,11 +7,13 @@ import net.corda.core.contracts.Amount
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.internal.FlowStateMachine
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.UntrustworthyData
|
||||
import net.corda.node.services.identity.InMemoryIdentityService
|
||||
import net.corda.node.shell.InteractiveShell
|
||||
import net.corda.testing.DUMMY_CA
|
||||
import net.corda.testing.DEV_TRUST_ROOT
|
||||
import net.corda.testing.MEGA_CORP
|
||||
import net.corda.testing.MEGA_CORP_IDENTITY
|
||||
import org.junit.Test
|
||||
@ -31,7 +33,7 @@ class InteractiveShellTest {
|
||||
override fun call() = a
|
||||
}
|
||||
|
||||
private val ids = InMemoryIdentityService(listOf(MEGA_CORP_IDENTITY), trustRoot = DUMMY_CA.certificate)
|
||||
private val ids = InMemoryIdentityService(listOf(MEGA_CORP_IDENTITY), trustRoot = DEV_TRUST_ROOT)
|
||||
private val om = JacksonSupport.createInMemoryMapper(ids, YAMLFactory())
|
||||
|
||||
private fun check(input: String, expected: String) {
|
||||
@ -69,4 +71,4 @@ class InteractiveShellTest {
|
||||
fun party() = check("party: \"${MEGA_CORP.name}\"", MEGA_CORP.name.toString())
|
||||
|
||||
class DummyFSM(val logic: FlowA) : FlowStateMachine<Any?> by mock()
|
||||
}
|
||||
}
|
||||
|
@ -96,8 +96,8 @@ class TwoPartyTradeFlowTests {
|
||||
val aliceNode = basketOfNodes.partyNodes[0]
|
||||
val bobNode = basketOfNodes.partyNodes[1]
|
||||
val bankNode = basketOfNodes.partyNodes[2]
|
||||
val cashIssuer = bankNode.info.legalIdentity.ref(1)
|
||||
val cpIssuer = bankNode.info.legalIdentity.ref(1, 2, 3)
|
||||
val cashIssuer = bankNode.info.chooseIdentity().ref(1)
|
||||
val cpIssuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
|
||||
|
||||
aliceNode.internals.disableDBCloseOnStop()
|
||||
bobNode.internals.disableDBCloseOnStop()
|
||||
@ -108,8 +108,8 @@ class TwoPartyTradeFlowTests {
|
||||
}
|
||||
|
||||
val alicesFakePaper = aliceNode.database.transaction {
|
||||
fillUpForSeller(false, cpIssuer, aliceNode.info.legalIdentity,
|
||||
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), null, notaryNode.info.notaryIdentity).second
|
||||
fillUpForSeller(false, cpIssuer, aliceNode.info.chooseIdentity(),
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notaryNode.info.notaryIdentity).second
|
||||
}
|
||||
|
||||
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
|
||||
@ -144,7 +144,7 @@ class TwoPartyTradeFlowTests {
|
||||
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
|
||||
val issuer = bankNode.info.legalIdentity.ref(1)
|
||||
val issuer = bankNode.info.chooseIdentity().ref(1)
|
||||
|
||||
aliceNode.internals.disableDBCloseOnStop()
|
||||
bobNode.internals.disableDBCloseOnStop()
|
||||
@ -155,8 +155,8 @@ class TwoPartyTradeFlowTests {
|
||||
}
|
||||
|
||||
val alicesFakePaper = aliceNode.database.transaction {
|
||||
fillUpForSeller(false, issuer, aliceNode.info.legalIdentity,
|
||||
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), null, notaryNode.info.notaryIdentity).second
|
||||
fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notaryNode.info.notaryIdentity).second
|
||||
}
|
||||
|
||||
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
|
||||
@ -197,21 +197,16 @@ class TwoPartyTradeFlowTests {
|
||||
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
var bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
|
||||
val issuer = bankNode.info.legalIdentity.ref(1, 2, 3)
|
||||
val issuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
|
||||
|
||||
// Let the nodes know about each other - normally the network map would handle this
|
||||
val allNodes = listOf(notaryNode, aliceNode, bobNode, bankNode)
|
||||
allNodes.forEach { node ->
|
||||
node.database.transaction {
|
||||
allNodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity -> node.services.identityService.verifyAndRegisterIdentity(identity) }
|
||||
}
|
||||
}
|
||||
mockNet.registerIdentities()
|
||||
|
||||
aliceNode.database.transaction {
|
||||
aliceNode.services.identityService.verifyAndRegisterIdentity(bobNode.info.legalIdentityAndCert)
|
||||
aliceNode.services.identityService.verifyAndRegisterIdentity(bobNode.info.chooseIdentityAndCert())
|
||||
}
|
||||
bobNode.database.transaction {
|
||||
bobNode.services.identityService.verifyAndRegisterIdentity(aliceNode.info.legalIdentityAndCert)
|
||||
bobNode.services.identityService.verifyAndRegisterIdentity(aliceNode.info.chooseIdentityAndCert())
|
||||
}
|
||||
aliceNode.internals.disableDBCloseOnStop()
|
||||
bobNode.internals.disableDBCloseOnStop()
|
||||
@ -226,8 +221,8 @@ class TwoPartyTradeFlowTests {
|
||||
issuedBy = issuer)
|
||||
}
|
||||
val alicesFakePaper = aliceNode.database.transaction {
|
||||
fillUpForSeller(false, issuer, aliceNode.info.legalIdentity,
|
||||
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), null, notaryNode.info.notaryIdentity).second
|
||||
fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), null, notaryNode.info.notaryIdentity).second
|
||||
}
|
||||
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
|
||||
val aliceFuture = runBuyerAndSeller(notaryNode, aliceNode, bobNode, "alice's paper".outputStateAndRef()).sellerResult
|
||||
@ -335,17 +330,12 @@ class TwoPartyTradeFlowTests {
|
||||
val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
|
||||
val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
|
||||
val bankNode = makeNodeWithTracking(notaryNode.network.myAddress, BOC.name)
|
||||
val issuer = bankNode.info.legalIdentity.ref(1, 2, 3)
|
||||
val issuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
|
||||
|
||||
mockNet.runNetwork()
|
||||
notaryNode.internals.ensureRegistered()
|
||||
|
||||
val allNodes = listOf(notaryNode, aliceNode, bobNode, bankNode)
|
||||
allNodes.forEach { node ->
|
||||
node.database.transaction {
|
||||
allNodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity -> node.services.identityService.verifyAndRegisterIdentity(identity) }
|
||||
}
|
||||
}
|
||||
mockNet.registerIdentities()
|
||||
|
||||
ledger(aliceNode.services, initialiseSerialization = false) {
|
||||
|
||||
@ -360,12 +350,12 @@ class TwoPartyTradeFlowTests {
|
||||
attachment(ByteArrayInputStream(stream.toByteArray()))
|
||||
}
|
||||
|
||||
val bobsFakeCash = fillUpForBuyer(false, issuer, AnonymousParty(bobNode.info.legalIdentity.owningKey),
|
||||
val bobsFakeCash = fillUpForBuyer(false, issuer, AnonymousParty(bobNode.info.chooseIdentity().owningKey),
|
||||
notaryNode.info.notaryIdentity).second
|
||||
val bobsSignedTxns = insertFakeTransactions(bobsFakeCash, bobNode, notaryNode, bankNode)
|
||||
val alicesFakePaper = aliceNode.database.transaction {
|
||||
fillUpForSeller(false, issuer, aliceNode.info.legalIdentity,
|
||||
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), attachmentID, notaryNode.info.notaryIdentity).second
|
||||
fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), attachmentID, notaryNode.info.notaryIdentity).second
|
||||
}
|
||||
val alicesSignedTxns = insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
|
||||
|
||||
@ -446,19 +436,12 @@ class TwoPartyTradeFlowTests {
|
||||
val aliceNode = makeNodeWithTracking(notaryNode.network.myAddress, ALICE.name)
|
||||
val bobNode = makeNodeWithTracking(notaryNode.network.myAddress, BOB.name)
|
||||
val bankNode = makeNodeWithTracking(notaryNode.network.myAddress, BOC.name)
|
||||
val issuer = bankNode.info.legalIdentity.ref(1, 2, 3)
|
||||
val issuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
|
||||
|
||||
mockNet.runNetwork()
|
||||
notaryNode.internals.ensureRegistered()
|
||||
|
||||
val allNodes = listOf(notaryNode, aliceNode, bobNode, bankNode)
|
||||
allNodes.forEach { node ->
|
||||
node.database.transaction {
|
||||
allNodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity ->
|
||||
node.services.identityService.verifyAndRegisterIdentity(identity)
|
||||
}
|
||||
}
|
||||
}
|
||||
mockNet.registerIdentities()
|
||||
|
||||
ledger(aliceNode.services, initialiseSerialization = false) {
|
||||
// Insert a prospectus type attachment into the commercial paper transaction.
|
||||
@ -478,8 +461,8 @@ class TwoPartyTradeFlowTests {
|
||||
insertFakeTransactions(bobsFakeCash, bobNode, notaryNode, bankNode)
|
||||
|
||||
val alicesFakePaper = aliceNode.database.transaction {
|
||||
fillUpForSeller(false, issuer, aliceNode.info.legalIdentity,
|
||||
1200.DOLLARS `issued by` bankNode.info.legalIdentity.ref(0), attachmentID, notaryNode.info.notaryIdentity).second
|
||||
fillUpForSeller(false, issuer, aliceNode.info.chooseIdentity(),
|
||||
1200.DOLLARS `issued by` bankNode.info.chooseIdentity().ref(0), attachmentID, notaryNode.info.notaryIdentity).second
|
||||
}
|
||||
|
||||
insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, bankNode)
|
||||
@ -556,7 +539,7 @@ class TwoPartyTradeFlowTests {
|
||||
anonymous: Boolean = true): RunResult {
|
||||
val buyerFlows: Observable<out FlowLogic<*>> = buyerNode.internals.registerInitiatedFlow(BuyerAcceptor::class.java)
|
||||
val firstBuyerFiber = buyerFlows.toFuture().map { it.stateMachine }
|
||||
val seller = SellerInitiator(buyerNode.info.legalIdentity, notaryNode.info, assetToSell, 1000.DOLLARS, anonymous)
|
||||
val seller = SellerInitiator(buyerNode.info.chooseIdentity(), notaryNode.info, assetToSell, 1000.DOLLARS, anonymous)
|
||||
val sellerResult = sellerNode.services.startFlow(seller).resultFuture
|
||||
return RunResult(firstBuyerFiber, sellerResult, seller.stateMachine.id)
|
||||
}
|
||||
@ -569,10 +552,10 @@ class TwoPartyTradeFlowTests {
|
||||
val anonymous: Boolean) : FlowLogic<SignedTransaction>() {
|
||||
@Suspendable
|
||||
override fun call(): SignedTransaction {
|
||||
val me = if (anonymous) {
|
||||
serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.legalIdentityAndCert, false)
|
||||
val myParty = if (anonymous) {
|
||||
serviceHub.keyManagementService.freshKeyAndCert(serviceHub.myInfo.chooseIdentityAndCert(), false)
|
||||
} else {
|
||||
serviceHub.myInfo.legalIdentityAndCert
|
||||
serviceHub.myInfo.chooseIdentityAndCert()
|
||||
}
|
||||
send(buyer, TestTx(notary.notaryIdentity, price, anonymous))
|
||||
return subFlow(Seller(
|
||||
@ -580,7 +563,7 @@ class TwoPartyTradeFlowTests {
|
||||
notary,
|
||||
assetToSell,
|
||||
price,
|
||||
me))
|
||||
myParty))
|
||||
}
|
||||
}
|
||||
|
||||
@ -608,25 +591,20 @@ class TwoPartyTradeFlowTests {
|
||||
val aliceNode = mockNet.createPartyNode(notaryNode.network.myAddress, ALICE.name)
|
||||
val bobNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOB.name)
|
||||
val bankNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
|
||||
val issuer = bankNode.info.legalIdentity.ref(1, 2, 3)
|
||||
val issuer = bankNode.info.chooseIdentity().ref(1, 2, 3)
|
||||
|
||||
mockNet.runNetwork()
|
||||
notaryNode.internals.ensureRegistered()
|
||||
|
||||
// Let the nodes know about each other - normally the network map would handle this
|
||||
val allNodes = listOf(notaryNode, aliceNode, bobNode, bankNode)
|
||||
allNodes.forEach { node ->
|
||||
node.database.transaction {
|
||||
allNodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity -> node.services.identityService.verifyAndRegisterIdentity(identity) }
|
||||
}
|
||||
}
|
||||
mockNet.registerIdentities()
|
||||
|
||||
val bobsBadCash = bobNode.database.transaction {
|
||||
fillUpForBuyer(bobError, issuer, bobNode.info.legalIdentity,
|
||||
fillUpForBuyer(bobError, issuer, bobNode.info.chooseIdentity(),
|
||||
notaryNode.info.notaryIdentity).second
|
||||
}
|
||||
val alicesFakePaper = aliceNode.database.transaction {
|
||||
fillUpForSeller(aliceError, issuer, aliceNode.info.legalIdentity,
|
||||
fillUpForSeller(aliceError, issuer, aliceNode.info.chooseIdentity(),
|
||||
1200.DOLLARS `issued by` issuer, null, notaryNode.info.notaryIdentity).second
|
||||
}
|
||||
|
||||
@ -661,10 +639,14 @@ class TwoPartyTradeFlowTests {
|
||||
val signed = wtxToSign.map {
|
||||
val id = it.id
|
||||
val sigs = mutableListOf<TransactionSignature>()
|
||||
sigs.add(node.services.keyManagementService.sign(SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(node.services.legalIdentityKey).schemeNumberID)), node.services.legalIdentityKey))
|
||||
val nodeKey = node.info.chooseIdentity().owningKey
|
||||
sigs.add(node.services.keyManagementService.sign(SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(nodeKey).schemeNumberID)), nodeKey))
|
||||
sigs.add(notaryNode.services.keyManagementService.sign(SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(notaryNode.services.notaryIdentityKey).schemeNumberID)), notaryNode.services.notaryIdentityKey))
|
||||
extraSigningNodes.forEach { currentNode ->
|
||||
sigs.add(currentNode.services.keyManagementService.sign(SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(currentNode.info.legalIdentity.owningKey).schemeNumberID)), currentNode.info.legalIdentity.owningKey))
|
||||
sigs.add(currentNode.services.keyManagementService.sign(
|
||||
SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(currentNode.info.chooseIdentity().owningKey).schemeNumberID)),
|
||||
currentNode.info.chooseIdentity().owningKey)
|
||||
)
|
||||
}
|
||||
SignedTransaction(it, sigs)
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.getTestPartyAndCertificate
|
||||
@ -45,7 +46,7 @@ class NotaryChangeTests {
|
||||
clientNodeA = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress)
|
||||
clientNodeB = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress)
|
||||
newNotaryNode = mockNet.createNode(networkMapAddress = oldNotaryNode.network.myAddress, advertisedServices = ServiceInfo(SimpleNotaryService.type))
|
||||
|
||||
mockNet.registerIdentities()
|
||||
mockNet.runNetwork() // Clear network map registration messages
|
||||
oldNotaryNode.internals.ensureRegistered()
|
||||
}
|
||||
@ -133,7 +134,7 @@ class NotaryChangeTests {
|
||||
}
|
||||
|
||||
private fun issueEncumberedState(node: StartedNode<*>, notaryNode: StartedNode<*>): WireTransaction {
|
||||
val owner = node.info.legalIdentity.ref(0)
|
||||
val owner = node.info.chooseIdentity().ref(0)
|
||||
val notary = notaryNode.info.notaryIdentity
|
||||
|
||||
val stateA = DummyContract.SingleOwnerState(Random().nextInt(), owner.party)
|
||||
@ -161,7 +162,7 @@ class NotaryChangeTests {
|
||||
}
|
||||
|
||||
fun issueState(node: StartedNode<*>, notaryNode: StartedNode<*>): StateAndRef<*> {
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.legalIdentity.ref(0))
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.chooseIdentity().ref(0))
|
||||
val signedByNode = node.services.signInitialTransaction(tx)
|
||||
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
|
||||
node.services.recordTransactions(stx)
|
||||
@ -170,7 +171,7 @@ fun issueState(node: StartedNode<*>, notaryNode: StartedNode<*>): StateAndRef<*>
|
||||
|
||||
fun issueMultiPartyState(nodeA: StartedNode<*>, nodeB: StartedNode<*>, notaryNode: StartedNode<*>): StateAndRef<DummyContract.MultiOwnerState> {
|
||||
val state = TransactionState(DummyContract.MultiOwnerState(0,
|
||||
listOf(nodeA.info.legalIdentity, nodeB.info.legalIdentity)), DUMMY_PROGRAM_ID, notaryNode.info.notaryIdentity)
|
||||
listOf(nodeA.info.chooseIdentity(), nodeB.info.chooseIdentity())), DUMMY_PROGRAM_ID, notaryNode.info.notaryIdentity)
|
||||
val tx = TransactionBuilder(notary = notaryNode.info.notaryIdentity).withItems(state, dummyCommand())
|
||||
val signedByA = nodeA.services.signInitialTransaction(tx)
|
||||
val signedByAB = nodeB.services.addSignature(signedByA)
|
||||
@ -182,7 +183,7 @@ fun issueMultiPartyState(nodeA: StartedNode<*>, nodeB: StartedNode<*>, notaryNod
|
||||
}
|
||||
|
||||
fun issueInvalidState(node: StartedNode<*>, notary: Party): StateAndRef<*> {
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notary, node.info.legalIdentity.ref(0))
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notary, node.info.chooseIdentity().ref(0))
|
||||
tx.setTimeWindow(Instant.now(), 30.seconds)
|
||||
val stx = node.services.signInitialTransaction(tx)
|
||||
node.services.recordTransactions(stx)
|
||||
|
@ -77,7 +77,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
|
||||
val dataSourceProps = makeTestDataSourceProperties()
|
||||
val databaseProperties = makeTestDatabaseProperties()
|
||||
database = configureDatabase(dataSourceProps, databaseProperties, createIdentityService = ::makeTestIdentityService)
|
||||
val identityService = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
|
||||
val identityService = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
|
||||
val kms = MockKeyManagementService(identityService, ALICE_KEY)
|
||||
|
||||
database.transaction {
|
||||
@ -277,7 +277,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
|
||||
database.transaction {
|
||||
apply {
|
||||
val freshKey = services.keyManagementService.freshKey()
|
||||
val state = TestState(FlowLogicRefFactoryImpl.createForRPC(TestFlowLogic::class.java, increment), instant, services.myInfo.legalIdentity)
|
||||
val state = TestState(FlowLogicRefFactoryImpl.createForRPC(TestFlowLogic::class.java, increment), instant, services.myInfo.chooseIdentity())
|
||||
val builder = TransactionBuilder(null).apply {
|
||||
addOutputState(state, DUMMY_PROGRAM_ID, DUMMY_NOTARY)
|
||||
addCommand(Command(), freshKey)
|
||||
|
@ -22,6 +22,7 @@ import net.corda.node.services.statemachine.StateMachineManager
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
@ -62,14 +63,14 @@ class ScheduledFlowTests {
|
||||
@Suspendable
|
||||
override fun call() {
|
||||
val scheduledState = ScheduledState(serviceHub.clock.instant(),
|
||||
serviceHub.myInfo.legalIdentity, destination)
|
||||
serviceHub.myInfo.chooseIdentity(), destination)
|
||||
|
||||
val notary = serviceHub.networkMapCache.getAnyNotary()
|
||||
val builder = TransactionBuilder(notary)
|
||||
.addOutputState(scheduledState, DUMMY_PROGRAM_ID)
|
||||
.addCommand(dummyCommand(serviceHub.legalIdentityKey))
|
||||
.addCommand(dummyCommand(ourIdentity.owningKey))
|
||||
val tx = serviceHub.signInitialTransaction(builder)
|
||||
subFlow(FinalityFlow(tx, setOf(serviceHub.myInfo.legalIdentity)))
|
||||
subFlow(FinalityFlow(tx, setOf(serviceHub.myInfo.chooseIdentity())))
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +81,7 @@ class ScheduledFlowTests {
|
||||
val state = serviceHub.toStateAndRef<ScheduledState>(stateRef)
|
||||
val scheduledState = state.state.data
|
||||
// Only run flow over states originating on this node
|
||||
if (scheduledState.source != serviceHub.myInfo.legalIdentity) {
|
||||
if (scheduledState.source != serviceHub.myInfo.chooseIdentity()) {
|
||||
return
|
||||
}
|
||||
require(!scheduledState.processed) { "State should not have been previously processed" }
|
||||
@ -89,7 +90,7 @@ class ScheduledFlowTests {
|
||||
val builder = TransactionBuilder(notary)
|
||||
.addInputState(state)
|
||||
.addOutputState(newStateOutput, DUMMY_PROGRAM_ID)
|
||||
.addCommand(dummyCommand(serviceHub.legalIdentityKey))
|
||||
.addCommand(dummyCommand(serviceHub.myInfo.chooseIdentity().owningKey))
|
||||
val tx = serviceHub.signInitialTransaction(builder)
|
||||
subFlow(FinalityFlow(tx, setOf(scheduledState.source, scheduledState.destination)))
|
||||
}
|
||||
@ -126,7 +127,7 @@ class ScheduledFlowTests {
|
||||
countScheduledFlows++
|
||||
}
|
||||
}
|
||||
nodeA.services.startFlow(InsertInitialStateFlow(nodeB.info.legalIdentity))
|
||||
nodeA.services.startFlow(InsertInitialStateFlow(nodeB.info.chooseIdentity()))
|
||||
mockNet.waitQuiescent()
|
||||
val stateFromA = nodeA.database.transaction {
|
||||
nodeA.services.vaultQueryService.queryBy<ScheduledState>().states.single()
|
||||
@ -144,8 +145,8 @@ class ScheduledFlowTests {
|
||||
val N = 100
|
||||
val futures = mutableListOf<CordaFuture<*>>()
|
||||
for (i in 0..N - 1) {
|
||||
futures.add(nodeA.services.startFlow(InsertInitialStateFlow(nodeB.info.legalIdentity)).resultFuture)
|
||||
futures.add(nodeB.services.startFlow(InsertInitialStateFlow(nodeA.info.legalIdentity)).resultFuture)
|
||||
futures.add(nodeA.services.startFlow(InsertInitialStateFlow(nodeB.info.chooseIdentity())).resultFuture)
|
||||
futures.add(nodeB.services.startFlow(InsertInitialStateFlow(nodeA.info.chooseIdentity())).resultFuture)
|
||||
}
|
||||
mockNet.waitQuiescent()
|
||||
|
||||
|
@ -30,6 +30,8 @@ import net.corda.testing.ALICE
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.CHARLIE
|
||||
import net.corda.testing.DUMMY_MAP
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.chooseIdentityAndCert
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetwork.MockNode
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
@ -203,7 +205,7 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
|
||||
}
|
||||
|
||||
private fun StartedNode<*>.identityQuery(): NodeInfo? {
|
||||
val request = QueryIdentityRequest(info.legalIdentityAndCert, network.myAddress)
|
||||
val request = QueryIdentityRequest(services.myInfo.chooseIdentityAndCert(), network.myAddress)
|
||||
val response = services.networkService.sendRequest<QueryIdentityResponse>(QUERY_TOPIC, request, mapServiceNode.network.myAddress)
|
||||
mockNet.runNetwork()
|
||||
return response.getOrThrow().node
|
||||
@ -221,7 +223,7 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
|
||||
}
|
||||
val expires = Instant.now() + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
|
||||
val nodeRegistration = NodeRegistration(info, distinctSerial, addOrRemove, expires)
|
||||
val request = RegistrationRequest(nodeRegistration.toWire(services.keyManagementService, services.legalIdentityKey), network.myAddress)
|
||||
val request = RegistrationRequest(nodeRegistration.toWire(services.keyManagementService, info.chooseIdentity().owningKey), network.myAddress)
|
||||
val response = services.networkService.sendRequest<RegistrationResponse>(REGISTER_TOPIC, request, mapServiceNode.network.myAddress)
|
||||
mockNet.runNetwork()
|
||||
return response
|
||||
|
@ -16,7 +16,6 @@ import net.corda.node.utilities.X509Utilities
|
||||
import net.corda.testing.*
|
||||
import org.junit.Test
|
||||
import java.security.cert.CertificateFactory
|
||||
import javax.security.auth.x500.X500Principal
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertNull
|
||||
@ -27,7 +26,7 @@ import kotlin.test.assertNull
|
||||
class InMemoryIdentityServiceTests {
|
||||
@Test
|
||||
fun `get all identities`() {
|
||||
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
|
||||
val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
|
||||
// Nothing registered, so empty set
|
||||
assertNull(service.getAllIdentities().firstOrNull())
|
||||
|
||||
@ -45,7 +44,7 @@ class InMemoryIdentityServiceTests {
|
||||
|
||||
@Test
|
||||
fun `get identity by key`() {
|
||||
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
|
||||
val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
|
||||
assertNull(service.partyFromKey(ALICE_PUBKEY))
|
||||
service.verifyAndRegisterIdentity(ALICE_IDENTITY)
|
||||
assertEquals(ALICE, service.partyFromKey(ALICE_PUBKEY))
|
||||
@ -54,14 +53,13 @@ class InMemoryIdentityServiceTests {
|
||||
|
||||
@Test
|
||||
fun `get identity by name with no registered identities`() {
|
||||
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
|
||||
val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
|
||||
assertNull(service.partyFromX500Name(ALICE.name))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `get identity by substring match`() {
|
||||
val trustRoot = DUMMY_CA
|
||||
val service = InMemoryIdentityService(trustRoot = trustRoot.certificate)
|
||||
val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
|
||||
service.verifyAndRegisterIdentity(ALICE_IDENTITY)
|
||||
service.verifyAndRegisterIdentity(BOB_IDENTITY)
|
||||
val alicente = getTestPartyAndCertificate(CordaX500Name(organisation = "Alicente Worldwide", locality = "London", country = "GB"), generateKeyPair().public)
|
||||
@ -73,7 +71,7 @@ class InMemoryIdentityServiceTests {
|
||||
|
||||
@Test
|
||||
fun `get identity by name`() {
|
||||
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
|
||||
val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
|
||||
val identities = listOf("Org A", "Org B", "Org C")
|
||||
.map { getTestPartyAndCertificate(CordaX500Name(organisation = it, locality = "London", country = "GB"), generateKeyPair().public) }
|
||||
assertNull(service.partyFromX500Name(identities.first().name))
|
||||
@ -90,7 +88,7 @@ class InMemoryIdentityServiceTests {
|
||||
val rootKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val rootCert = X509Utilities.createSelfSignedCACertificate(ALICE.name, rootKey)
|
||||
val txKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
|
||||
val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT)
|
||||
// TODO: Generate certificate with an EdDSA key rather than ECDSA
|
||||
val identity = Party(rootCert.cert)
|
||||
val txIdentity = AnonymousParty(txKey.public)
|
||||
@ -107,12 +105,11 @@ class InMemoryIdentityServiceTests {
|
||||
*/
|
||||
@Test
|
||||
fun `get anonymous identity by key`() {
|
||||
val trustRoot = DUMMY_CA
|
||||
val (alice, aliceTxIdentity) = createParty(ALICE.name, trustRoot)
|
||||
val (_, bobTxIdentity) = createParty(ALICE.name, trustRoot)
|
||||
val (alice, aliceTxIdentity) = createParty(ALICE.name, DEV_CA)
|
||||
val (_, bobTxIdentity) = createParty(ALICE.name, DEV_CA)
|
||||
|
||||
// Now we have identities, construct the service and let it know about both
|
||||
val service = InMemoryIdentityService(setOf(alice), emptySet(), trustRoot.certificate.cert)
|
||||
val service = InMemoryIdentityService(setOf(alice), emptySet(), DEV_TRUST_ROOT)
|
||||
service.verifyAndRegisterIdentity(aliceTxIdentity)
|
||||
|
||||
var actual = service.certificateFromKey(aliceTxIdentity.party.owningKey)
|
||||
@ -131,12 +128,11 @@ class InMemoryIdentityServiceTests {
|
||||
@Test
|
||||
fun `assert ownership`() {
|
||||
withTestSerialization {
|
||||
val trustRoot = DUMMY_CA
|
||||
val (alice, anonymousAlice) = createParty(ALICE.name, trustRoot)
|
||||
val (bob, anonymousBob) = createParty(BOB.name, trustRoot)
|
||||
val (alice, anonymousAlice) = createParty(ALICE.name, DEV_CA)
|
||||
val (bob, anonymousBob) = createParty(BOB.name, DEV_CA)
|
||||
|
||||
// Now we have identities, construct the service and let it know about both
|
||||
val service = InMemoryIdentityService(setOf(alice, bob), emptySet(), trustRoot.certificate.cert)
|
||||
val service = InMemoryIdentityService(setOf(alice, bob), emptySet(), DEV_TRUST_ROOT)
|
||||
|
||||
service.verifyAndRegisterIdentity(anonymousAlice)
|
||||
service.verifyAndRegisterIdentity(anonymousBob)
|
||||
@ -152,8 +148,8 @@ class InMemoryIdentityServiceTests {
|
||||
}
|
||||
|
||||
assertFailsWith<IllegalArgumentException> {
|
||||
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded)
|
||||
val subject = CordaX500Name.build(X500Principal(trustRoot.certificate.subject.encoded))
|
||||
val owningKey = Crypto.decodePublicKey(DEV_CA.certificate.subjectPublicKeyInfo.encoded)
|
||||
val subject = CordaX500Name.build(DEV_CA.certificate.cert.subjectX500Principal)
|
||||
service.assertOwnership(Party(subject, owningKey), anonymousAlice.party.anonymise())
|
||||
}
|
||||
}
|
||||
@ -175,7 +171,7 @@ class InMemoryIdentityServiceTests {
|
||||
@Test
|
||||
fun `deanonymising a well known identity`() {
|
||||
val expected = ALICE
|
||||
val actual = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate).partyFromAnonymous(expected)
|
||||
val actual = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT).partyFromAnonymous(expected)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.After
|
||||
@ -41,16 +42,16 @@ class NetworkMapCacheTest {
|
||||
val entropy = BigInteger.valueOf(24012017L)
|
||||
val nodeA = mockNet.createNode(nodeFactory = MockNetwork.DefaultFactory, legalName = ALICE.name, entropyRoot = entropy, advertisedServices = ServiceInfo(NetworkMapService.type))
|
||||
val nodeB = mockNet.createNode(nodeFactory = MockNetwork.DefaultFactory, legalName = BOB.name, entropyRoot = entropy, advertisedServices = ServiceInfo(NetworkMapService.type))
|
||||
assertEquals(nodeA.info.legalIdentity, nodeB.info.legalIdentity)
|
||||
assertEquals(nodeA.info.chooseIdentity(), nodeB.info.chooseIdentity())
|
||||
|
||||
mockNet.runNetwork()
|
||||
|
||||
// Node A currently knows only about itself, so this returns node A
|
||||
assertEquals(nodeA.services.networkMapCache.getNodeByLegalIdentityKey(nodeA.info.legalIdentity.owningKey), nodeA.info)
|
||||
assertEquals(nodeA.services.networkMapCache.getNodesByLegalIdentityKey(nodeA.info.chooseIdentity().owningKey).singleOrNull(), nodeA.info)
|
||||
|
||||
nodeA.services.networkMapCache.addNode(nodeB.info)
|
||||
// The details of node B write over those for node A
|
||||
assertEquals(nodeA.services.networkMapCache.getNodeByLegalIdentityKey(nodeA.info.legalIdentity.owningKey), nodeB.info)
|
||||
assertEquals(nodeA.services.networkMapCache.getNodesByLegalIdentityKey(nodeA.info.chooseIdentity().owningKey).singleOrNull(), nodeB.info)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -62,7 +63,7 @@ class NetworkMapCacheTest {
|
||||
val expected = n1.info
|
||||
|
||||
mockNet.runNetwork()
|
||||
val actual = n0.database.transaction { node0Cache.getNodeByLegalIdentity(n1.info.legalIdentity) }
|
||||
val actual = n0.database.transaction { node0Cache.getNodeByLegalIdentity(n1.info.chooseIdentity()) }
|
||||
assertEquals(expected, actual)
|
||||
|
||||
// TODO: Should have a test case with anonymous lookup
|
||||
@ -73,14 +74,16 @@ class NetworkMapCacheTest {
|
||||
val nodes = mockNet.createSomeNodes(1)
|
||||
val n0 = nodes.mapNode
|
||||
val n1 = nodes.partyNodes[0]
|
||||
val n0Identity = n0.info.chooseIdentity()
|
||||
val n1Identity = n1.info.chooseIdentity()
|
||||
val node0Cache = n0.services.networkMapCache as PersistentNetworkMapCache
|
||||
mockNet.runNetwork()
|
||||
n0.database.transaction {
|
||||
assertThat(node0Cache.getNodeByLegalIdentity(n1.info.legalIdentity) != null)
|
||||
assertThat(node0Cache.getNodeByLegalIdentity(n1Identity) != null)
|
||||
node0Cache.removeNode(n1.info)
|
||||
assertThat(node0Cache.getNodeByLegalIdentity(n1.info.legalIdentity) == null)
|
||||
assertThat(node0Cache.getNodeByLegalIdentity(n0.info.legalIdentity) != null)
|
||||
assertThat(node0Cache.getNodeByLegalName(n1.info.legalIdentity.name) == null)
|
||||
assertThat(node0Cache.getNodeByLegalIdentity(n1Identity) == null)
|
||||
assertThat(node0Cache.getNodeByLegalIdentity(n0Identity) != null)
|
||||
assertThat(node0Cache.getNodeByLegalName(n1Identity.name) == null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class PersistentIdentityServiceTests {
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
val databaseAndServices = MockServices.makeTestDatabaseAndMockServices(keys = emptyList(), createIdentityService = { PersistentIdentityService(trustRoot = DUMMY_CA.certificate) })
|
||||
val databaseAndServices = MockServices.makeTestDatabaseAndMockServices(keys = emptyList(), createIdentityService = { PersistentIdentityService(trustRoot = DEV_TRUST_ROOT) })
|
||||
database = databaseAndServices.first
|
||||
services = databaseAndServices.second
|
||||
identityService = services.identityService
|
||||
@ -152,9 +152,8 @@ class PersistentIdentityServiceTests {
|
||||
*/
|
||||
@Test
|
||||
fun `get anonymous identity by key`() {
|
||||
val trustRoot = DUMMY_CA
|
||||
val (alice, aliceTxIdentity) = createParty(ALICE.name, trustRoot)
|
||||
val (_, bobTxIdentity) = createParty(ALICE.name, trustRoot)
|
||||
val (alice, aliceTxIdentity) = createParty(ALICE.name, DEV_CA)
|
||||
val (_, bobTxIdentity) = createParty(ALICE.name, DEV_CA)
|
||||
|
||||
// Now we have identities, construct the service and let it know about both
|
||||
database.transaction {
|
||||
@ -186,9 +185,8 @@ class PersistentIdentityServiceTests {
|
||||
@Test
|
||||
fun `assert ownership`() {
|
||||
withTestSerialization {
|
||||
val trustRoot = DUMMY_CA
|
||||
val (alice, anonymousAlice) = createParty(ALICE.name, trustRoot)
|
||||
val (bob, anonymousBob) = createParty(BOB.name, trustRoot)
|
||||
val (alice, anonymousAlice) = createParty(ALICE.name, DEV_CA)
|
||||
val (bob, anonymousBob) = createParty(BOB.name, DEV_CA)
|
||||
|
||||
database.transaction {
|
||||
// Now we have identities, construct the service and let it know about both
|
||||
@ -213,9 +211,9 @@ class PersistentIdentityServiceTests {
|
||||
}
|
||||
|
||||
assertFailsWith<IllegalArgumentException> {
|
||||
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded)
|
||||
val owningKey = Crypto.decodePublicKey(DEV_CA.certificate.subjectPublicKeyInfo.encoded)
|
||||
database.transaction {
|
||||
val subject = CordaX500Name.build(X500Principal(trustRoot.certificate.subject.encoded))
|
||||
val subject = CordaX500Name.build(DEV_CA.certificate.cert.subjectX500Principal)
|
||||
identityService.assertOwnership(Party(subject, owningKey), anonymousAlice.party.anonymise())
|
||||
}
|
||||
}
|
||||
@ -224,9 +222,8 @@ class PersistentIdentityServiceTests {
|
||||
|
||||
@Test
|
||||
fun `Test Persistence`() {
|
||||
val trustRoot = DUMMY_CA
|
||||
val (alice, anonymousAlice) = createParty(ALICE.name, trustRoot)
|
||||
val (bob, anonymousBob) = createParty(BOB.name, trustRoot)
|
||||
val (alice, anonymousAlice) = createParty(ALICE.name, DEV_CA)
|
||||
val (bob, anonymousBob) = createParty(BOB.name, DEV_CA)
|
||||
|
||||
database.transaction {
|
||||
// Register well known identities
|
||||
@ -239,7 +236,7 @@ class PersistentIdentityServiceTests {
|
||||
|
||||
// Create new identity service mounted onto same DB
|
||||
val newPersistentIdentityService = database.transaction {
|
||||
PersistentIdentityService(trustRoot = DUMMY_CA.certificate)
|
||||
PersistentIdentityService(trustRoot = DEV_TRUST_ROOT)
|
||||
}
|
||||
|
||||
database.transaction {
|
||||
|
@ -14,6 +14,7 @@ import net.corda.testing.ALICE
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.CHARLIE
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.NodeBasedTest
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Before
|
||||
@ -32,7 +33,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||
nodes.forEach { it.internals.nodeReadyFuture.get() } // Need to wait for network map registration, as these tests are ran without waiting.
|
||||
nodes.forEach {
|
||||
infos.add(it.info)
|
||||
addressesMap[it.info.legalIdentity.name] = it.info.addresses[0]
|
||||
addressesMap[it.info.chooseIdentity().name] = it.info.addresses[0]
|
||||
it.dispose() // We want them to communicate with NetworkMapService to save data to cache.
|
||||
}
|
||||
}
|
||||
@ -42,10 +43,10 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||
val alice = startNodesWithPort(listOf(ALICE), noNetworkMap = true)[0]
|
||||
val netCache = alice.services.networkMapCache as PersistentNetworkMapCache
|
||||
alice.database.transaction {
|
||||
val res = netCache.getNodeByLegalIdentity(alice.info.legalIdentity)
|
||||
val res = netCache.getNodeByLegalIdentity(alice.info.chooseIdentity())
|
||||
assertEquals(alice.info, res)
|
||||
val res2 = netCache.getNodeByLegalName(DUMMY_NOTARY.name)
|
||||
assertEquals(infos.filter { it.legalIdentity.name == DUMMY_NOTARY.name }.singleOrNull(), res2)
|
||||
assertEquals(infos.filter { DUMMY_NOTARY.name in it.legalIdentitiesAndCerts.map { it.name } }.singleOrNull(), res2)
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +67,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||
assert(NetworkMapService.type !in alice.info.advertisedServices.map { it.info.type })
|
||||
assertEquals(NullNetworkMapService, alice.inNodeNetworkMapService)
|
||||
assertEquals(infos.size, partyNodes.size)
|
||||
assertEquals(infos.map { it.legalIdentity }.toSet(), partyNodes.map { it.legalIdentity }.toSet())
|
||||
assertEquals(infos.flatMap { it.legalIdentities }.toSet(), partyNodes.flatMap { it.legalIdentities }.toSet())
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -78,7 +79,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||
nodes.forEach {
|
||||
val partyNodes = it.services.networkMapCache.partyNodes
|
||||
assertEquals(infos.size, partyNodes.size)
|
||||
assertEquals(infos.map { it.legalIdentity }.toSet(), partyNodes.map { it.legalIdentity }.toSet())
|
||||
assertEquals(infos.flatMap { it.legalIdentities }.toSet(), partyNodes.flatMap { it.legalIdentities }.toSet())
|
||||
}
|
||||
checkConnectivity(nodes)
|
||||
}
|
||||
@ -92,7 +93,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||
nodes.forEach {
|
||||
val partyNodes = it.services.networkMapCache.partyNodes
|
||||
assertEquals(infos.size, partyNodes.size)
|
||||
assertEquals(infos.map { it.legalIdentity }.toSet(), partyNodes.map { it.legalIdentity }.toSet())
|
||||
assertEquals(infos.flatMap { it.legalIdentities }.toSet(), partyNodes.flatMap { it.legalIdentities }.toSet())
|
||||
}
|
||||
checkConnectivity(nodes)
|
||||
}
|
||||
@ -115,20 +116,20 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||
// Start 2 nodes pointing at network map, but don't start network map service.
|
||||
val otherNodes = startNodesWithPort(parties, noNetworkMap = false)
|
||||
otherNodes.forEach { node ->
|
||||
assert(infos.any { it.legalIdentity == node.info.legalIdentity })
|
||||
assert(infos.any { it.legalIdentitiesAndCerts.toSet() == node.info.legalIdentitiesAndCerts.toSet() })
|
||||
}
|
||||
// Start node that is not in databases of other nodes. Point to NMS. Which has't started yet.
|
||||
val charlie = startNodesWithPort(listOf(CHARLIE), noNetworkMap = false)[0]
|
||||
otherNodes.forEach {
|
||||
assert(charlie.info.legalIdentity !in it.services.networkMapCache.partyNodes.map { it.legalIdentity })
|
||||
assert(charlie.info.chooseIdentity() !in it.services.networkMapCache.partyNodes.flatMap { it.legalIdentities })
|
||||
}
|
||||
// Start Network Map and see that charlie node appears in caches.
|
||||
val nms = startNodesWithPort(listOf(DUMMY_NOTARY), noNetworkMap = false)[0]
|
||||
nms.internals.startupComplete.get()
|
||||
assert(nms.inNodeNetworkMapService != NullNetworkMapService)
|
||||
assert(infos.any {it.legalIdentity == nms.info.legalIdentity})
|
||||
assert(infos.any { it.legalIdentities.toSet() == nms.info.legalIdentities.toSet() })
|
||||
otherNodes.forEach {
|
||||
assert(nms.info.legalIdentity in it.services.networkMapCache.partyNodes.map { it.legalIdentity })
|
||||
assert(nms.info.chooseIdentity() in it.services.networkMapCache.partyNodes.map { it.chooseIdentity() })
|
||||
}
|
||||
charlie.internals.nodeReadyFuture.get() // Finish registration.
|
||||
checkConnectivity(listOf(otherNodes[0], nms)) // Checks connectivity from A to NMS.
|
||||
@ -136,7 +137,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||
val cacheB = otherNodes[1].services.networkMapCache.partyNodes
|
||||
val cacheC = charlie.services.networkMapCache.partyNodes
|
||||
assertEquals(4, cacheC.size) // Charlie fetched data from NetworkMap
|
||||
assert(charlie.info.legalIdentity in cacheB.map { it.legalIdentity }) // Other nodes also fetched data from Network Map with node C.
|
||||
assert(charlie.info.chooseIdentity() in cacheB.map { it.chooseIdentity() }) // Other nodes also fetched data from Network Map with node C.
|
||||
assertEquals(cacheA.toSet(), cacheB.toSet())
|
||||
assertEquals(cacheA.toSet(), cacheC.toSet())
|
||||
}
|
||||
@ -163,7 +164,7 @@ class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||
nodes.forEach { node1 ->
|
||||
nodes.forEach { node2 ->
|
||||
node2.internals.registerInitiatedFlow(SendBackFlow::class.java)
|
||||
val resultFuture = node1.services.startFlow(SendFlow(node2.info.legalIdentity)).resultFuture
|
||||
val resultFuture = node1.services.startFlow(SendFlow(node2.info.chooseIdentity())).resultFuture
|
||||
assertThat(resultFuture.getOrThrow()).isEqualTo("Hello!")
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import net.corda.node.internal.StartedNode
|
||||
import net.corda.node.services.NotifyTransactionHandler
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.MEGA_CORP
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.After
|
||||
@ -45,8 +46,8 @@ class DataVendingServiceTests {
|
||||
val nodes = mockNet.createSomeNodes(2)
|
||||
val vaultServiceNode = nodes.partyNodes[0]
|
||||
val registerNode = nodes.partyNodes[1]
|
||||
val beneficiary = vaultServiceNode.info.legalIdentity
|
||||
val deposit = registerNode.info.legalIdentity.ref(1)
|
||||
val beneficiary = vaultServiceNode.info.chooseIdentity()
|
||||
val deposit = registerNode.info.chooseIdentity().ref(1)
|
||||
mockNet.runNetwork()
|
||||
|
||||
// Generate an issuance transaction
|
||||
@ -75,7 +76,7 @@ class DataVendingServiceTests {
|
||||
val nodes = mockNet.createSomeNodes(2)
|
||||
val vaultServiceNode = nodes.partyNodes[0]
|
||||
val registerNode = nodes.partyNodes[1]
|
||||
val beneficiary = vaultServiceNode.info.legalIdentity
|
||||
val beneficiary = vaultServiceNode.info.chooseIdentity()
|
||||
val deposit = MEGA_CORP.ref(1)
|
||||
mockNet.runNetwork()
|
||||
|
||||
@ -97,7 +98,7 @@ class DataVendingServiceTests {
|
||||
|
||||
private fun StartedNode<*>.sendNotifyTx(tx: SignedTransaction, walletServiceNode: StartedNode<*>) {
|
||||
walletServiceNode.internals.registerInitiatedFlow(InitiateNotifyTxFlow::class.java)
|
||||
services.startFlow(NotifyTxFlow(walletServiceNode.info.legalIdentity, tx))
|
||||
services.startFlow(NotifyTxFlow(walletServiceNode.info.chooseIdentity(), tx))
|
||||
mockNet.runNetwork()
|
||||
}
|
||||
|
||||
|
@ -94,14 +94,7 @@ class FlowFrameworkTests {
|
||||
mockNet.runNetwork()
|
||||
|
||||
// We don't create a network map, so manually handle registrations
|
||||
val nodes = listOf(node1, node2, notary1, notary2)
|
||||
nodes.forEach { node ->
|
||||
node.database.transaction {
|
||||
nodes.map { it.services.myInfo.legalIdentityAndCert }.forEach { identity ->
|
||||
node.services.identityService.verifyAndRegisterIdentity(identity)
|
||||
}
|
||||
}
|
||||
}
|
||||
mockNet.registerIdentities()
|
||||
}
|
||||
|
||||
@After
|
||||
@ -128,7 +121,7 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `exception while fiber suspended`() {
|
||||
node2.registerFlowFactory(ReceiveFlow::class) { SendFlow("Hello", it) }
|
||||
val flow = ReceiveFlow(node2.info.legalIdentity)
|
||||
val flow = ReceiveFlow(node2.info.chooseIdentity())
|
||||
val fiber = node1.services.startFlow(flow) as FlowStateMachineImpl
|
||||
// Before the flow runs change the suspend action to throw an exception
|
||||
val exceptionDuringSuspend = Exception("Thrown during suspend")
|
||||
@ -147,7 +140,7 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `flow restarted just after receiving payload`() {
|
||||
node2.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() }
|
||||
node1.services.startFlow(SendFlow("Hello", node2.info.legalIdentity))
|
||||
node1.services.startFlow(SendFlow("Hello", node2.info.chooseIdentity()))
|
||||
|
||||
// We push through just enough messages to get only the payload sent
|
||||
node2.pumpReceive()
|
||||
@ -199,7 +192,7 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `flow loaded from checkpoint will respond to messages from before start`() {
|
||||
node1.registerFlowFactory(ReceiveFlow::class) { SendFlow("Hello", it) }
|
||||
node2.services.startFlow(ReceiveFlow(node1.info.legalIdentity).nonTerminating()) // Prepare checkpointed receive flow
|
||||
node2.services.startFlow(ReceiveFlow(node1.info.chooseIdentity()).nonTerminating()) // Prepare checkpointed receive flow
|
||||
// Make sure the add() has finished initial processing.
|
||||
node2.smm.executor.flush()
|
||||
node2.internals.disableDBCloseOnStop()
|
||||
@ -221,7 +214,7 @@ class FlowFrameworkTests {
|
||||
mockNet.runNetwork()
|
||||
|
||||
// Kick off first send and receive
|
||||
node2.services.startFlow(PingPongFlow(node3.info.legalIdentity, payload))
|
||||
node2.services.startFlow(PingPongFlow(node3.info.chooseIdentity(), payload))
|
||||
node2.database.transaction {
|
||||
assertEquals(1, node2.checkpointStorage.checkpoints().size)
|
||||
}
|
||||
@ -266,7 +259,7 @@ class FlowFrameworkTests {
|
||||
node2.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() }
|
||||
node3.registerFlowFactory(SendFlow::class) { ReceiveFlow(it).nonTerminating() }
|
||||
val payload = "Hello World"
|
||||
node1.services.startFlow(SendFlow(payload, node2.info.legalIdentity, node3.info.legalIdentity))
|
||||
node1.services.startFlow(SendFlow(payload, node2.info.chooseIdentity(), node3.info.chooseIdentity()))
|
||||
mockNet.runNetwork()
|
||||
val node2Flow = node2.getSingleFlow<ReceiveFlow>().first
|
||||
val node3Flow = node3.getSingleFlow<ReceiveFlow>().first
|
||||
@ -299,7 +292,7 @@ class FlowFrameworkTests {
|
||||
val node3Payload = "Test 2"
|
||||
node2.registerFlowFactory(ReceiveFlow::class) { SendFlow(node2Payload, it) }
|
||||
node3.registerFlowFactory(ReceiveFlow::class) { SendFlow(node3Payload, it) }
|
||||
val multiReceiveFlow = ReceiveFlow(node2.info.legalIdentity, node3.info.legalIdentity).nonTerminating()
|
||||
val multiReceiveFlow = ReceiveFlow(node2.info.chooseIdentity(), node3.info.chooseIdentity()).nonTerminating()
|
||||
node1.services.startFlow(multiReceiveFlow)
|
||||
node1.internals.acceptableLiveFiberCountOnStop = 1
|
||||
mockNet.runNetwork()
|
||||
@ -324,7 +317,7 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `both sides do a send as their first IO request`() {
|
||||
node2.registerFlowFactory(PingPongFlow::class) { PingPongFlow(it, 20L) }
|
||||
node1.services.startFlow(PingPongFlow(node2.info.legalIdentity, 10L))
|
||||
node1.services.startFlow(PingPongFlow(node2.info.chooseIdentity(), 10L))
|
||||
mockNet.runNetwork()
|
||||
|
||||
assertSessionTransfers(
|
||||
@ -347,13 +340,13 @@ class FlowFrameworkTests {
|
||||
notary1.info.notaryIdentity)).resultFuture.getOrThrow()
|
||||
// We pay a couple of times, the notary picking should go round robin
|
||||
for (i in 1..3) {
|
||||
val flow = node1.services.startFlow(CashPaymentFlow(500.DOLLARS, node2.info.legalIdentity))
|
||||
val flow = node1.services.startFlow(CashPaymentFlow(500.DOLLARS, node2.info.chooseIdentity()))
|
||||
mockNet.runNetwork()
|
||||
flow.resultFuture.getOrThrow()
|
||||
}
|
||||
val endpoint = mockNet.messagingNetwork.endpoint(notary1.network.myAddress as InMemoryMessagingNetwork.PeerHandle)!!
|
||||
val party1Info = notary1.services.networkMapCache.getPartyInfo(notary1.info.notaryIdentity)!!
|
||||
assertTrue(party1Info is PartyInfo.Service)
|
||||
assertTrue(party1Info is PartyInfo.DistributedNode)
|
||||
val notary1Address: MessageRecipients = endpoint.getAddressOfParty(notary1.services.networkMapCache.getPartyInfo(notary1.info.notaryIdentity)!!)
|
||||
assertThat(notary1Address).isInstanceOf(InMemoryMessagingNetwork.ServiceHandle::class.java)
|
||||
assertEquals(notary1Address, endpoint.getAddressOfParty(notary2.services.networkMapCache.getPartyInfo(notary2.info.notaryIdentity)!!))
|
||||
@ -396,7 +389,7 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `other side ends before doing expected send`() {
|
||||
node2.registerFlowFactory(ReceiveFlow::class) { NoOpFlow() }
|
||||
val resultFuture = node1.services.startFlow(ReceiveFlow(node2.info.legalIdentity)).resultFuture
|
||||
val resultFuture = node1.services.startFlow(ReceiveFlow(node2.info.chooseIdentity())).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
|
||||
resultFuture.getOrThrow()
|
||||
@ -409,7 +402,7 @@ class FlowFrameworkTests {
|
||||
val sessionEndReceived = Semaphore(0)
|
||||
receivedSessionMessagesObservable().filter { it.message is SessionEnd }.subscribe { sessionEndReceived.release() }
|
||||
val resultFuture = node1.services.startFlow(
|
||||
WaitForOtherSideEndBeforeSendAndReceive(node2.info.legalIdentity, sessionEndReceived)).resultFuture
|
||||
WaitForOtherSideEndBeforeSendAndReceive(node2.info.chooseIdentity(), sessionEndReceived)).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
|
||||
resultFuture.getOrThrow()
|
||||
@ -436,7 +429,7 @@ class FlowFrameworkTests {
|
||||
}
|
||||
val erroringFlowSteps = erroringFlowFuture.flatMap { it.progressSteps }
|
||||
|
||||
val receiveFlow = ReceiveFlow(node2.info.legalIdentity)
|
||||
val receiveFlow = ReceiveFlow(node2.info.chooseIdentity())
|
||||
val receiveFlowSteps = receiveFlow.progressSteps
|
||||
val receiveFlowResult = node1.services.startFlow(receiveFlow).resultFuture
|
||||
|
||||
@ -470,7 +463,7 @@ class FlowFrameworkTests {
|
||||
}
|
||||
val erroringFlowSteps = erroringFlow.flatMap { it.progressSteps }
|
||||
|
||||
val receivingFiber = node1.services.startFlow(ReceiveFlow(node2.info.legalIdentity)) as FlowStateMachineImpl
|
||||
val receivingFiber = node1.services.startFlow(ReceiveFlow(node2.info.chooseIdentity())) as FlowStateMachineImpl
|
||||
|
||||
mockNet.runNetwork()
|
||||
|
||||
@ -504,8 +497,8 @@ class FlowFrameworkTests {
|
||||
mockNet.runNetwork()
|
||||
|
||||
node3.registerFlowFactory(ReceiveFlow::class) { ExceptionFlow { MyFlowException("Chain") } }
|
||||
node2.registerFlowFactory(ReceiveFlow::class) { ReceiveFlow(node3.info.legalIdentity) }
|
||||
val receivingFiber = node1.services.startFlow(ReceiveFlow(node2.info.legalIdentity))
|
||||
node2.registerFlowFactory(ReceiveFlow::class) { ReceiveFlow(node3.info.chooseIdentity()) }
|
||||
val receivingFiber = node1.services.startFlow(ReceiveFlow(node2.info.chooseIdentity()))
|
||||
mockNet.runNetwork()
|
||||
assertThatExceptionOfType(MyFlowException::class.java)
|
||||
.isThrownBy { receivingFiber.resultFuture.getOrThrow() }
|
||||
@ -524,7 +517,7 @@ class FlowFrameworkTests {
|
||||
.map { it.stateMachine }
|
||||
node3.registerFlowFactory(ReceiveFlow::class) { ExceptionFlow { MyFlowException("Nothing useful") } }
|
||||
|
||||
val node1Fiber = node1.services.startFlow(ReceiveFlow(node2.info.legalIdentity, node3.info.legalIdentity)) as FlowStateMachineImpl
|
||||
val node1Fiber = node1.services.startFlow(ReceiveFlow(node2.info.chooseIdentity(), node3.info.chooseIdentity())) as FlowStateMachineImpl
|
||||
mockNet.runNetwork()
|
||||
|
||||
// Node 1 will terminate with the error it received from node 3 but it won't propagate that to node 2 (as it's
|
||||
@ -576,7 +569,7 @@ class FlowFrameworkTests {
|
||||
}
|
||||
|
||||
node2.registerFlowFactory(AskForExceptionFlow::class) { ConditionalExceptionFlow(it, "Hello") }
|
||||
val resultFuture = node1.services.startFlow(RetryOnExceptionFlow(node2.info.legalIdentity)).resultFuture
|
||||
val resultFuture = node1.services.startFlow(RetryOnExceptionFlow(node2.info.chooseIdentity())).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertThat(resultFuture.getOrThrow()).isEqualTo("Hello")
|
||||
}
|
||||
@ -584,7 +577,7 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `serialisation issue in counterparty`() {
|
||||
node2.registerFlowFactory(ReceiveFlow::class) { SendFlow(NonSerialisableData(1), it) }
|
||||
val result = node1.services.startFlow(ReceiveFlow(node2.info.legalIdentity)).resultFuture
|
||||
val result = node1.services.startFlow(ReceiveFlow(node2.info.chooseIdentity())).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
|
||||
result.getOrThrow()
|
||||
@ -596,7 +589,7 @@ class FlowFrameworkTests {
|
||||
node2.registerFlowFactory(ReceiveFlow::class) {
|
||||
ExceptionFlow { NonSerialisableFlowException(NonSerialisableData(1)) }
|
||||
}
|
||||
val result = node1.services.startFlow(ReceiveFlow(node2.info.legalIdentity)).resultFuture
|
||||
val result = node1.services.startFlow(ReceiveFlow(node2.info.chooseIdentity())).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertThatExceptionOfType(FlowException::class.java).isThrownBy {
|
||||
result.getOrThrow()
|
||||
@ -607,13 +600,13 @@ class FlowFrameworkTests {
|
||||
fun `wait for transaction`() {
|
||||
val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity)
|
||||
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
|
||||
.addCommand(dummyCommand(node1.services.legalIdentityKey))
|
||||
.addCommand(dummyCommand(node1.info.chooseIdentity().owningKey))
|
||||
val stx = node1.services.signInitialTransaction(ptx)
|
||||
|
||||
val committerFiber = node1.registerFlowFactory(WaitingFlows.Waiter::class) {
|
||||
WaitingFlows.Committer(it)
|
||||
}.map { it.stateMachine }
|
||||
val waiterStx = node2.services.startFlow(WaitingFlows.Waiter(stx, node1.info.legalIdentity)).resultFuture
|
||||
val waiterStx = node2.services.startFlow(WaitingFlows.Waiter(stx, node1.info.chooseIdentity())).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertThat(waiterStx.getOrThrow()).isEqualTo(committerFiber.getOrThrow().resultFuture.getOrThrow())
|
||||
}
|
||||
@ -628,7 +621,7 @@ class FlowFrameworkTests {
|
||||
node1.registerFlowFactory(WaitingFlows.Waiter::class) {
|
||||
WaitingFlows.Committer(it) { throw Exception("Error") }
|
||||
}
|
||||
val waiter = node2.services.startFlow(WaitingFlows.Waiter(stx, node1.info.legalIdentity)).resultFuture
|
||||
val waiter = node2.services.startFlow(WaitingFlows.Waiter(stx, node1.info.chooseIdentity())).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
|
||||
waiter.getOrThrow()
|
||||
@ -639,13 +632,13 @@ class FlowFrameworkTests {
|
||||
fun `verify vault query service is tokenizable by force checkpointing within a flow`() {
|
||||
val ptx = TransactionBuilder(notary = notary1.info.notaryIdentity)
|
||||
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
|
||||
.addCommand(dummyCommand(node1.services.legalIdentityKey))
|
||||
.addCommand(dummyCommand(node1.info.chooseIdentity().owningKey))
|
||||
val stx = node1.services.signInitialTransaction(ptx)
|
||||
|
||||
node1.registerFlowFactory(VaultQueryFlow::class) {
|
||||
WaitingFlows.Committer(it)
|
||||
}
|
||||
val result = node2.services.startFlow(VaultQueryFlow(stx, node1.info.legalIdentity)).resultFuture
|
||||
val result = node2.services.startFlow(VaultQueryFlow(stx, node1.info.chooseIdentity())).resultFuture
|
||||
|
||||
mockNet.runNetwork()
|
||||
assertThat(result.getOrThrow()).isEmpty()
|
||||
@ -654,14 +647,14 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `customised client flow`() {
|
||||
val receiveFlowFuture = node2.registerFlowFactory(SendFlow::class) { ReceiveFlow(it) }
|
||||
node1.services.startFlow(CustomSendFlow("Hello", node2.info.legalIdentity)).resultFuture
|
||||
node1.services.startFlow(CustomSendFlow("Hello", node2.info.chooseIdentity())).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertThat(receiveFlowFuture.getOrThrow().receivedPayloads).containsOnly("Hello")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `customised client flow which has annotated @InitiatingFlow again`() {
|
||||
val result = node1.services.startFlow(IncorrectCustomSendFlow("Hello", node2.info.legalIdentity)).resultFuture
|
||||
val result = node1.services.startFlow(IncorrectCustomSendFlow("Hello", node2.info.chooseIdentity())).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertThatExceptionOfType(IllegalArgumentException::class.java).isThrownBy {
|
||||
result.getOrThrow()
|
||||
@ -671,7 +664,7 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `upgraded initiating flow`() {
|
||||
node2.registerFlowFactory(UpgradedFlow::class, initiatedFlowVersion = 1) { SendFlow("Old initiated", it) }
|
||||
val result = node1.services.startFlow(UpgradedFlow(node2.info.legalIdentity)).resultFuture
|
||||
val result = node1.services.startFlow(UpgradedFlow(node2.info.chooseIdentity())).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertThat(receivedSessionMessages).startsWith(
|
||||
node1 sent sessionInit(UpgradedFlow::class, flowVersion = 2) to node2,
|
||||
@ -685,19 +678,19 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `upgraded initiated flow`() {
|
||||
node2.registerFlowFactory(SendFlow::class, initiatedFlowVersion = 2) { UpgradedFlow(it) }
|
||||
val initiatingFlow = SendFlow("Old initiating", node2.info.legalIdentity)
|
||||
val initiatingFlow = SendFlow("Old initiating", node2.info.chooseIdentity())
|
||||
node1.services.startFlow(initiatingFlow)
|
||||
mockNet.runNetwork()
|
||||
assertThat(receivedSessionMessages).startsWith(
|
||||
node1 sent sessionInit(SendFlow::class, flowVersion = 1, payload = "Old initiating") to node2,
|
||||
node2 sent sessionConfirm(flowVersion = 2) to node1
|
||||
)
|
||||
assertThat(initiatingFlow.getFlowInfo(node2.info.legalIdentity).flowVersion).isEqualTo(2)
|
||||
assertThat(initiatingFlow.getFlowInfo(node2.info.chooseIdentity()).flowVersion).isEqualTo(2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unregistered flow`() {
|
||||
val future = node1.services.startFlow(SendFlow("Hello", node2.info.legalIdentity)).resultFuture
|
||||
val future = node1.services.startFlow(SendFlow("Hello", node2.info.chooseIdentity())).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertThatExceptionOfType(UnexpectedFlowEndException::class.java)
|
||||
.isThrownBy { future.getOrThrow() }
|
||||
@ -725,7 +718,7 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `single inlined sub-flow`() {
|
||||
node2.registerFlowFactory(SendAndReceiveFlow::class) { SingleInlinedSubFlow(it) }
|
||||
val result = node1.services.startFlow(SendAndReceiveFlow(node2.info.legalIdentity, "Hello")).resultFuture
|
||||
val result = node1.services.startFlow(SendAndReceiveFlow(node2.info.chooseIdentity(), "Hello")).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertThat(result.getOrThrow()).isEqualTo("HelloHello")
|
||||
}
|
||||
@ -733,7 +726,7 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `double inlined sub-flow`() {
|
||||
node2.registerFlowFactory(SendAndReceiveFlow::class) { DoubleInlinedSubFlow(it) }
|
||||
val result = node1.services.startFlow(SendAndReceiveFlow(node2.info.legalIdentity, "Hello")).resultFuture
|
||||
val result = node1.services.startFlow(SendAndReceiveFlow(node2.info.chooseIdentity(), "Hello")).resultFuture
|
||||
mockNet.runNetwork()
|
||||
assertThat(result.getOrThrow()).isEqualTo("HelloHello")
|
||||
}
|
||||
@ -788,7 +781,7 @@ class FlowFrameworkTests {
|
||||
|
||||
private fun StartedNode<*>.sendSessionMessage(message: SessionMessage, destination: StartedNode<*>) {
|
||||
services.networkService.apply {
|
||||
val address = getAddressOfParty(PartyInfo.Node(destination.info))
|
||||
val address = getAddressOfParty(PartyInfo.SingleNode(destination.info.chooseIdentity(), emptyList()))
|
||||
send(createMessage(StateMachineManager.sessionTopic, message.serialize().bytes), address)
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import net.corda.core.utilities.seconds
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.node.MockNetwork
|
||||
@ -54,7 +55,7 @@ class NotaryServiceTests {
|
||||
val inputState = issueState(clientNode)
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
.setTimeWindow(Instant.now(), 30.seconds)
|
||||
clientNode.services.signInitialTransaction(tx)
|
||||
}
|
||||
@ -70,7 +71,7 @@ class NotaryServiceTests {
|
||||
val inputState = issueState(clientNode)
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
clientNode.services.signInitialTransaction(tx)
|
||||
}
|
||||
|
||||
@ -85,7 +86,7 @@ class NotaryServiceTests {
|
||||
val inputState = issueState(clientNode)
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
.setTimeWindow(Instant.now().plusSeconds(3600), 30.seconds)
|
||||
clientNode.services.signInitialTransaction(tx)
|
||||
}
|
||||
@ -102,7 +103,7 @@ class NotaryServiceTests {
|
||||
val inputState = issueState(clientNode)
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
clientNode.services.signInitialTransaction(tx)
|
||||
}
|
||||
|
||||
@ -122,14 +123,14 @@ class NotaryServiceTests {
|
||||
val stx = run {
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
clientNode.services.signInitialTransaction(tx)
|
||||
}
|
||||
val stx2 = run {
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
.addInputState(inputState)
|
||||
.addInputState(issueState(clientNode))
|
||||
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
clientNode.services.signInitialTransaction(tx)
|
||||
}
|
||||
|
||||
@ -154,7 +155,7 @@ class NotaryServiceTests {
|
||||
}
|
||||
|
||||
fun issueState(node: StartedNode<*>): StateAndRef<*> {
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.legalIdentity.ref(0))
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.chooseIdentity().ref(0))
|
||||
val signedByNode = node.services.signInitialTransaction(tx)
|
||||
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
|
||||
node.services.recordTransactions(stx)
|
||||
|
@ -17,6 +17,7 @@ import net.corda.node.services.issueInvalidState
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.MEGA_CORP_KEY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.node.MockNetwork
|
||||
@ -56,7 +57,7 @@ class ValidatingNotaryServiceTests {
|
||||
val inputState = issueInvalidState(clientNode, notaryNode.info.notaryIdentity)
|
||||
val tx = TransactionBuilder(notaryNode.info.notaryIdentity)
|
||||
.addInputState(inputState)
|
||||
.addCommand(dummyCommand(clientNode.services.legalIdentityKey))
|
||||
.addCommand(dummyCommand(clientNode.info.chooseIdentity().owningKey))
|
||||
clientNode.services.signInitialTransaction(tx)
|
||||
}
|
||||
|
||||
@ -97,7 +98,7 @@ class ValidatingNotaryServiceTests {
|
||||
}
|
||||
|
||||
fun issueState(node: StartedNode<*>): StateAndRef<*> {
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.legalIdentity.ref(0))
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notaryNode.info.notaryIdentity, node.info.chooseIdentity().ref(0))
|
||||
val signedByNode = node.services.signInitialTransaction(tx)
|
||||
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
|
||||
node.services.recordTransactions(stx)
|
||||
|
@ -445,7 +445,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
|
||||
val megaCorpServices = MockServices(MEGA_CORP_KEY)
|
||||
|
||||
database.transaction {
|
||||
val freshKey = services.legalIdentityKey
|
||||
val freshKey = services.myInfo.chooseIdentity().owningKey
|
||||
|
||||
// Issue a txn to Send us some Money
|
||||
val usefulBuilder = TransactionBuilder(null).apply {
|
||||
@ -477,11 +477,11 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
|
||||
fun `is ownable state relevant`() {
|
||||
val service = (services.vaultService as NodeVaultService)
|
||||
val amount = Amount(1000, Issued(BOC.ref(1), GBP))
|
||||
val wellKnownCash = Cash.State(amount, services.myInfo.legalIdentity)
|
||||
val wellKnownCash = Cash.State(amount, services.myInfo.chooseIdentity())
|
||||
val myKeys = services.keyManagementService.filterMyKeys(listOf(wellKnownCash.owner.owningKey))
|
||||
assertTrue { service.isRelevant(wellKnownCash, myKeys.toSet()) }
|
||||
|
||||
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(services.myInfo.legalIdentityAndCert, false)
|
||||
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(services.myInfo.chooseIdentityAndCert(), false)
|
||||
val anonymousCash = Cash.State(amount, anonymousIdentity.party)
|
||||
val anonymousKeys = services.keyManagementService.filterMyKeys(listOf(anonymousCash.owner.owningKey))
|
||||
assertTrue { service.isRelevant(anonymousCash, anonymousKeys.toSet()) }
|
||||
@ -501,14 +501,14 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
|
||||
service.updates.subscribe(this)
|
||||
}
|
||||
|
||||
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(services.myInfo.legalIdentityAndCert, false)
|
||||
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(services.myInfo.chooseIdentityAndCert(), false)
|
||||
val thirdPartyIdentity = AnonymousParty(generateKeyPair().public)
|
||||
val amount = Amount(1000, Issued(BOC.ref(1), GBP))
|
||||
|
||||
// Issue then move some cash
|
||||
val issueTx = TransactionBuilder(services.myInfo.legalIdentity).apply {
|
||||
val issueTx = TransactionBuilder(services.myInfo.chooseIdentity()).apply {
|
||||
Cash().generateIssue(this,
|
||||
amount, anonymousIdentity.party, services.myInfo.legalIdentity)
|
||||
amount, anonymousIdentity.party, services.myInfo.chooseIdentity())
|
||||
}.toWireTransaction()
|
||||
val cashState = StateAndRef(issueTx.outputs.single(), StateRef(issueTx.id, 0))
|
||||
|
||||
@ -516,7 +516,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
|
||||
val expectedIssueUpdate = Vault.Update(emptySet(), setOf(cashState), null)
|
||||
|
||||
database.transaction {
|
||||
val moveTx = TransactionBuilder(services.myInfo.legalIdentity).apply {
|
||||
val moveTx = TransactionBuilder(services.myInfo.chooseIdentity()).apply {
|
||||
Cash.generateSpend(services, this, Amount(1000, GBP), thirdPartyIdentity)
|
||||
}.toWireTransaction()
|
||||
service.notify(moveTx)
|
||||
@ -530,13 +530,13 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `correct updates are generated when changing notaries`() {
|
||||
val service = (services.vaultService as NodeVaultService)
|
||||
val notary = services.myInfo.legalIdentity
|
||||
val notary = services.myInfo.chooseIdentity()
|
||||
|
||||
val vaultSubscriber = TestSubscriber<Vault.Update<*>>().apply {
|
||||
service.updates.subscribe(this)
|
||||
}
|
||||
|
||||
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(services.myInfo.legalIdentityAndCert, false)
|
||||
val anonymousIdentity = services.keyManagementService.freshKeyAndCert(services.myInfo.chooseIdentityAndCert(), false)
|
||||
val thirdPartyIdentity = AnonymousParty(generateKeyPair().public)
|
||||
val amount = Amount(1000, Issued(BOC.ref(1), GBP))
|
||||
|
||||
|
@ -235,7 +235,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
||||
val dummyIssueBuilder = TransactionBuilder(notary = DUMMY_NOTARY).apply {
|
||||
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)), DUMMY_LINEAR_CONTRACT_PROGRAM_ID)
|
||||
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)), DUMMY_LINEAR_CONTRACT_PROGRAM_ID)
|
||||
addCommand(dummyCommand(notaryServices.legalIdentityKey))
|
||||
addCommand(dummyCommand(notaryServices.myInfo.chooseIdentity().owningKey))
|
||||
}
|
||||
val dummyIssue = notaryServices.signInitialTransaction(dummyIssueBuilder)
|
||||
|
||||
@ -255,7 +255,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
||||
database.transaction { // Issue a linear state
|
||||
val dummyIssueBuilder = TransactionBuilder(notary = DUMMY_NOTARY)
|
||||
.addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)), DUMMY_LINEAR_CONTRACT_PROGRAM_ID)
|
||||
.addCommand(dummyCommand(notaryServices.legalIdentityKey))
|
||||
.addCommand(dummyCommand(notaryServices.myInfo.chooseIdentity().owningKey))
|
||||
val dummyIssuePtx = notaryServices.signInitialTransaction(dummyIssueBuilder)
|
||||
val dummyIssue = services.addSignature(dummyIssuePtx)
|
||||
|
||||
@ -271,7 +271,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
||||
val dummyMoveBuilder = TransactionBuilder(notary = DUMMY_NOTARY)
|
||||
.addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)), DUMMY_LINEAR_CONTRACT_PROGRAM_ID)
|
||||
.addInputState(dummyIssue.tx.outRef<LinearState>(0))
|
||||
.addCommand(dummyCommand(notaryServices.legalIdentityKey))
|
||||
.addCommand(dummyCommand(notaryServices.myInfo.chooseIdentity().owningKey))
|
||||
|
||||
val dummyMove = notaryServices.signInitialTransaction(dummyMoveBuilder)
|
||||
|
||||
@ -347,7 +347,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
||||
addOutputState(DummyDealContract.State(ref = "999", participants = listOf(freshIdentity)), DUMMY_DEAL_PROGRAM_ID)
|
||||
addInputState(linearStates.first())
|
||||
addInputState(deals.first())
|
||||
addCommand(dummyCommand(notaryServices.legalIdentityKey))
|
||||
addCommand(dummyCommand(notaryServices.myInfo.chooseIdentity().owningKey))
|
||||
}
|
||||
|
||||
val dummyMove = notaryServices.signInitialTransaction(dummyMoveBuilder)
|
||||
|
@ -25,6 +25,7 @@ import net.corda.core.utilities.ProgressTracker
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.testing.DUMMY_BANK_B
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.driver.poll
|
||||
import java.io.InputStream
|
||||
import java.net.HttpURLConnection
|
||||
@ -117,7 +118,7 @@ class AttachmentDemoFlow(val otherSide: Party, val notary: Party, val hash: Secu
|
||||
// Create a trivial transaction with an output that describes the attachment, and the attachment itself
|
||||
val ptx = TransactionBuilder(notary)
|
||||
.addOutputState(AttachmentContract.State(hash), ATTACHMENT_PROGRAM_ID)
|
||||
.addCommand(AttachmentContract.Command, serviceHub.legalIdentityKey)
|
||||
.addCommand(AttachmentContract.Command, serviceHub.myInfo.chooseIdentity().owningKey)
|
||||
.addAttachment(hash)
|
||||
|
||||
progressTracker.currentStep = SIGNING
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user