diff --git a/core/src/test/kotlin/net/corda/core/flows/TxKeyFlowUtilitiesTests.kt b/core/src/test/kotlin/net/corda/core/flows/TxKeyFlowUtilitiesTests.kt index 88084bcb9e..662a807269 100644 --- a/core/src/test/kotlin/net/corda/core/flows/TxKeyFlowUtilitiesTests.kt +++ b/core/src/test/kotlin/net/corda/core/flows/TxKeyFlowUtilitiesTests.kt @@ -4,7 +4,6 @@ import net.corda.core.identity.Party import net.corda.core.utilities.ALICE import net.corda.core.utilities.BOB import net.corda.core.utilities.DUMMY_NOTARY -import net.corda.testing.MOCK_IDENTITY_SERVICE import net.corda.testing.node.MockNetwork import org.junit.Before import org.junit.Test @@ -17,7 +16,6 @@ class TxKeyFlowUtilitiesTests { @Before fun before() { net = MockNetwork(false) - net.identities += MOCK_IDENTITY_SERVICE.identities } @Test diff --git a/finance/src/test/kotlin/net/corda/flows/IssuerFlowTest.kt b/finance/src/test/kotlin/net/corda/flows/IssuerFlowTest.kt index 1056c9ff1b..4721ca8aeb 100644 --- a/finance/src/test/kotlin/net/corda/flows/IssuerFlowTest.kt +++ b/finance/src/test/kotlin/net/corda/flows/IssuerFlowTest.kt @@ -4,11 +4,11 @@ import com.google.common.util.concurrent.ListenableFuture import net.corda.contracts.testing.calculateRandomlySizedAmounts import net.corda.core.contracts.Amount import net.corda.core.contracts.DOLLARS -import net.corda.core.contracts.PartyAndReference import net.corda.core.contracts.currency import net.corda.core.flows.FlowException import net.corda.core.flows.FlowStateMachine import net.corda.core.getOrThrow +import net.corda.core.identity.Party import net.corda.core.map import net.corda.core.serialization.OpaqueBytes import net.corda.core.transactions.SignedTransaction @@ -40,13 +40,14 @@ class IssuerFlowTest { bankClientNode = net.createPartyNode(notaryNode.info.address, MEGA_CORP.name) // using default IssueTo Party Reference - val issueToPartyAndRef = bankClientNode.info.legalIdentity.ref(OpaqueBytes.of(123)) - val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankClientNode, 1000000.DOLLARS, issueToPartyAndRef) + val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankClientNode, 1000000.DOLLARS, + bankClientNode.info.legalIdentity, OpaqueBytes.of(123)) assertEquals(issuerResult.get(), issuer.get().resultFuture.get()) // try to issue an amount of a restricted currency assertFailsWith { - runIssuerAndIssueRequester(bankOfCordaNode, bankClientNode, Amount(100000L, currency("BRL")), issueToPartyAndRef).issueRequestResult.getOrThrow() + runIssuerAndIssueRequester(bankOfCordaNode, bankClientNode, Amount(100000L, currency("BRL")), + bankClientNode.info.legalIdentity, OpaqueBytes.of(123)).issueRequestResult.getOrThrow() } bankOfCordaNode.stop() @@ -62,8 +63,8 @@ class IssuerFlowTest { bankOfCordaNode = net.createPartyNode(notaryNode.info.address, BOC.name) // using default IssueTo Party Reference - val issueToPartyAndRef = bankOfCordaNode.info.legalIdentity.ref(OpaqueBytes.of(123)) - val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankOfCordaNode, 1000000.DOLLARS, issueToPartyAndRef) + val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankOfCordaNode, 1000000.DOLLARS, + bankOfCordaNode.info.legalIdentity, OpaqueBytes.of(123)) assertEquals(issuerResult.get(), issuer.get().resultFuture.get()) bankOfCordaNode.stop() @@ -79,14 +80,12 @@ class IssuerFlowTest { bankOfCordaNode = net.createPartyNode(notaryNode.info.address, BOC.name) bankClientNode = net.createPartyNode(notaryNode.info.address, MEGA_CORP.name) - // using default IssueTo Party Reference - val issueToPartyAndRef = bankClientNode.info.legalIdentity.ref(OpaqueBytes.of(123)) - // this test exercises the Cashflow issue and move subflows to ensure consistent spending of issued states val amount = 10000.DOLLARS val amounts = calculateRandomlySizedAmounts(10000.DOLLARS, 10, 10, Random()) val handles = amounts.map { pennies -> - runIssuerAndIssueRequester(bankOfCordaNode, bankClientNode, Amount(pennies, amount.token), issueToPartyAndRef) + runIssuerAndIssueRequester(bankOfCordaNode, bankClientNode, Amount(pennies, amount.token), + bankClientNode.info.legalIdentity, OpaqueBytes.of(123)) } handles.forEach { require(it.issueRequestResult.get() is SignedTransaction) @@ -98,13 +97,14 @@ class IssuerFlowTest { } private fun runIssuerAndIssueRequester(issuerNode: MockNode, issueToNode: MockNode, - amount: Amount, issueToPartyAndRef: PartyAndReference): RunResult { - val resolvedIssuerParty = issuerNode.services.identityService.partyFromAnonymous(issueToPartyAndRef) ?: throw IllegalStateException() + amount: Amount, + party: Party, ref: OpaqueBytes): RunResult { + val issueToPartyAndRef = party.ref(ref) val issuerFuture = issuerNode.initiateSingleShotFlow(IssuerFlow.IssuanceRequester::class) { _ -> - IssuerFlow.Issuer(resolvedIssuerParty) + IssuerFlow.Issuer(party) }.map { it.stateMachine } - val issueRequest = IssuanceRequester(amount, resolvedIssuerParty, issueToPartyAndRef.reference, issuerNode.info.legalIdentity) + val issueRequest = IssuanceRequester(amount, party, issueToPartyAndRef.reference, issuerNode.info.legalIdentity) val issueRequestResultFuture = issueToNode.services.startFlow(issueRequest).resultFuture return IssuerFlowTest.RunResult(issuerFuture, issueRequestResultFuture) diff --git a/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt b/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt index 77b0d01c2a..25ebc637a4 100644 --- a/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt +++ b/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt @@ -20,9 +20,13 @@ import javax.annotation.concurrent.ThreadSafe /** * Simple identity service which caches parties and provides functionality for efficient lookup. + * + * @param identities initial set of identities for the service, typically only used for unit tests. + * @param certPaths initial set of certificate paths for the service, typically only used for unit tests. */ @ThreadSafe -class InMemoryIdentityService : SingletonSerializeAsToken(), IdentityService { +class InMemoryIdentityService(identities: Iterable = emptySet(), + certPaths: Map = emptyMap()) : SingletonSerializeAsToken(), IdentityService { companion object { private val log = loggerFor() } @@ -31,6 +35,12 @@ class InMemoryIdentityService : SingletonSerializeAsToken(), IdentityService { private val principalToParties = ConcurrentHashMap() private val partyToPath = ConcurrentHashMap() + init { + keyToParties.putAll(identities.associateBy { it.owningKey } ) + principalToParties.putAll(identities.associateBy { it.name }) + partyToPath.putAll(certPaths) + } + override fun registerIdentity(party: Party) { log.trace { "Registering identity $party" } keyToParties[party.owningKey] = party diff --git a/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt b/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt index 0a95b0613f..1cde75adcf 100644 --- a/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt +++ b/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt @@ -70,7 +70,6 @@ class TwoPartyTradeFlowTests { @Before fun before() { net = MockNetwork(false) - net.identities += MOCK_IDENTITY_SERVICE.identities LogHelper.setLevel("platform.trade", "core.contract.TransactionGroup", "recordingmap") } @@ -501,6 +500,8 @@ class TwoPartyTradeFlowTests { serviceHub.legalIdentityKey)) } + sellerNode.services.identityService.registerIdentity(buyerNode.info.legalIdentity) + buyerNode.services.identityService.registerIdentity(sellerNode.info.legalIdentity) val buyerFuture = buyerNode.initiateSingleShotFlow(SellerRunnerFlow::class) { otherParty -> Buyer(otherParty, notaryNode.info.notaryIdentity, 1000.DOLLARS, CommercialPaper.State::class.java) }.map { it.stateMachine } diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/simulation/IRSSimulation.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/simulation/IRSSimulation.kt index 979984f817..45b2f9a4d0 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/simulation/IRSSimulation.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/simulation/IRSSimulation.kt @@ -1,6 +1,7 @@ package net.corda.irs.simulation import co.paralleluniverse.fibers.Suspendable +import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import com.google.common.util.concurrent.FutureCallback import com.google.common.util.concurrent.Futures @@ -13,7 +14,6 @@ import net.corda.core.flatMap import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowStateMachine import net.corda.core.flows.InitiatingFlow -import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import net.corda.core.map import net.corda.core.node.services.linearHeadsOfType @@ -24,10 +24,10 @@ import net.corda.flows.TwoPartyDealFlow.AutoOffer import net.corda.flows.TwoPartyDealFlow.Instigator import net.corda.irs.contract.InterestRateSwap import net.corda.jackson.JacksonSupport +import net.corda.node.services.identity.InMemoryIdentityService import net.corda.node.utilities.transaction import net.corda.testing.initiateSingleShotFlow import net.corda.testing.node.InMemoryMessagingNetwork -import net.corda.testing.node.MockIdentityService import java.security.PublicKey import java.time.LocalDate import java.util.* @@ -37,7 +37,7 @@ import java.util.* * A simulation in which banks execute interest rate swaps with each other, including the fixing events. */ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, latencyInjector: InMemoryMessagingNetwork.LatencyCalculator?) : Simulation(networkSendManuallyPumped, runAsync, latencyInjector) { - val om = JacksonSupport.createInMemoryMapper(MockIdentityService(network.identities)) + lateinit var om: ObjectMapper init { currentDateAndTime = LocalDate.of(2016, 3, 8).atStartOfDay() @@ -47,6 +47,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten override fun startMainSimulation(): ListenableFuture { val future = SettableFuture.create() + om = JacksonSupport.createInMemoryMapper(InMemoryIdentityService((banks + regulators + networkMap).map { it.info.legalIdentity })) startIRSDealBetween(0, 1).success { // Next iteration is a pause. diff --git a/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt b/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt index a86f941765..13afa5e73a 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt @@ -11,6 +11,7 @@ import net.corda.core.flows.FlowLogic import net.corda.core.identity.Party import net.corda.core.node.ServiceHub import net.corda.core.node.VersionInfo +import net.corda.core.node.services.IdentityService import net.corda.core.serialization.OpaqueBytes import net.corda.core.toFuture import net.corda.core.transactions.TransactionBuilder @@ -18,17 +19,16 @@ import net.corda.core.utilities.* import net.corda.node.internal.AbstractNode import net.corda.node.internal.NetworkMapInfo import net.corda.node.services.config.* +import net.corda.node.services.identity.InMemoryIdentityService import net.corda.node.services.statemachine.FlowStateMachineImpl import net.corda.node.services.statemachine.StateMachineManager import net.corda.nodeapi.User import net.corda.nodeapi.config.SSLConfiguration -import net.corda.testing.node.MockIdentityService import net.corda.testing.node.MockServices import net.corda.testing.node.makeTestDataSourceProperties import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500NameBuilder import org.bouncycastle.asn1.x500.style.BCStyle -import java.net.ServerSocket import java.net.URL import java.nio.file.Files import java.nio.file.Path @@ -85,7 +85,7 @@ val BIG_CORP_PARTY_REF = BIG_CORP.ref(OpaqueBytes.of(1)).reference val ALL_TEST_KEYS: List get() = listOf(MEGA_CORP_KEY, MINI_CORP_KEY, ALICE_KEY, BOB_KEY, DUMMY_NOTARY_KEY) -val MOCK_IDENTITY_SERVICE: MockIdentityService get() = MockIdentityService(listOf(MEGA_CORP, MINI_CORP, DUMMY_NOTARY)) +val MOCK_IDENTITY_SERVICE: IdentityService get() = InMemoryIdentityService(listOf(MEGA_CORP, MINI_CORP, DUMMY_NOTARY)) val MOCK_VERSION_INFO = VersionInfo(1, "Mock release", "Mock revision", "Mock Vendor") diff --git a/test-utils/src/main/kotlin/net/corda/testing/node/MockNode.kt b/test-utils/src/main/kotlin/net/corda/testing/node/MockNode.kt index 3a549fad6c..4905acec1d 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/node/MockNode.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/node/MockNode.kt @@ -20,6 +20,7 @@ import net.corda.core.utilities.loggerFor import net.corda.node.internal.AbstractNode import net.corda.node.internal.ServiceFlowInfo import net.corda.node.services.config.NodeConfiguration +import net.corda.node.services.identity.InMemoryIdentityService import net.corda.node.services.keys.E2ETestKeyManagementService import net.corda.node.services.messaging.MessagingService import net.corda.node.services.network.InMemoryNetworkMapService @@ -166,7 +167,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false, .getOrThrow() } - override fun makeIdentityService() = MockIdentityService(mockNet.identities) + override fun makeIdentityService() = InMemoryIdentityService(mockNet.identities) override fun makeVaultService(dataSourceProperties: Properties): VaultService = NodeVaultService(services, dataSourceProperties) diff --git a/test-utils/src/main/kotlin/net/corda/testing/node/MockServices.kt b/test-utils/src/main/kotlin/net/corda/testing/node/MockServices.kt index 1412378714..7eb9e8c5dc 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/node/MockServices.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/node/MockServices.kt @@ -14,6 +14,7 @@ import net.corda.core.node.services.* import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.DUMMY_NOTARY +import net.corda.node.services.identity.InMemoryIdentityService import net.corda.node.services.persistence.InMemoryStateMachineRecordedTransactionMappingStorage import net.corda.node.services.schema.HibernateObserver import net.corda.node.services.schema.NodeSchemaService @@ -37,6 +38,7 @@ import java.security.cert.CertPath import java.security.cert.X509Certificate import java.time.Clock import java.util.* +import java.util.concurrent.ConcurrentHashMap import java.util.jar.JarInputStream import javax.annotation.concurrent.ThreadSafe @@ -62,7 +64,7 @@ open class MockServices(vararg val keys: KeyPair) : ServiceHub { } override val storageService: TxWritableStorageService = MockStorageService() - override val identityService: MockIdentityService = MockIdentityService(listOf(MEGA_CORP, MINI_CORP, DUMMY_NOTARY)) + override val identityService: IdentityService = InMemoryIdentityService(listOf(MEGA_CORP, MINI_CORP, DUMMY_NOTARY)) override val keyManagementService: KeyManagementService = MockKeyManagementService(*keys) override val vaultService: VaultService get() = throw UnsupportedOperationException() @@ -79,36 +81,6 @@ open class MockServices(vararg val keys: KeyPair) : ServiceHub { } } -@ThreadSafe -class MockIdentityService(val identities: List, - val certificates: List> = emptyList()) : IdentityService, SingletonSerializeAsToken() { - private val keyToParties: Map - get() = synchronized(identities) { identities.associateBy { it.owningKey } } - private val nameToParties: Map - get() = synchronized(identities) { identities.associateBy { it.name } } - private val anonymousToPath: Map> - get() = synchronized(certificates) { certificates.map { Pair(it.first, Pair(it.second, it.third)) }.toMap() } - - override fun registerIdentity(party: Party) { - throw UnsupportedOperationException() - } - - override fun getAllIdentities(): Iterable = ArrayList(keyToParties.values) - override fun partyFromAnonymous(party: AbstractParty): Party? = keyToParties[party.owningKey] - override fun partyFromAnonymous(partyRef: PartyAndReference): Party? = partyFromAnonymous(partyRef.party) - override fun partyFromKey(key: PublicKey): Party? = keyToParties[key] - override fun partyFromName(name: String): Party? = nameToParties[X500Name(name)] - override fun partyFromX500Name(principal: X500Name): Party? = nameToParties[principal] - - @Throws(IllegalStateException::class) - override fun assertOwnership(party: Party, anonymousParty: AnonymousParty) { - check(anonymousToPath[anonymousParty]?.first == party) - } - override fun pathForAnonymous(anonymousParty: AnonymousParty): CertPath? = anonymousToPath[anonymousParty]?.second - override fun registerPath(trustedRoot: X509Certificate, anonymousParty: AnonymousParty, path: CertPath) { throw UnsupportedOperationException() } -} - - class MockKeyManagementService(vararg initialKeys: KeyPair) : SingletonSerializeAsToken(), KeyManagementService { private val keyStore: MutableMap = initialKeys.associateByTo(HashMap(), { it.public }, { it.private })