From 794ce039585c2203235739e8ef53c175ec322c3a Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Fri, 19 May 2017 11:22:47 +0100 Subject: [PATCH] Remove mock identity service Remove mock identity service and merge it with the in memory identity service. The two services provide extremely similar functionality, and having two different version for production/test risks subtle implementation differences. On that note, this patch includes changes to a number of tests which worked only with mock identity service. --- .../core/flows/TxKeyFlowUtilitiesTests.kt | 2 -- .../kotlin/net/corda/flows/IssuerFlowTest.kt | 28 +++++++-------- .../identity/InMemoryIdentityService.kt | 12 ++++++- .../node/messaging/TwoPartyTradeFlowTests.kt | 3 +- .../net/corda/irs/simulation/IRSSimulation.kt | 7 ++-- .../kotlin/net/corda/testing/CoreTestUtils.kt | 6 ++-- .../kotlin/net/corda/testing/node/MockNode.kt | 3 +- .../net/corda/testing/node/MockServices.kt | 34 ++----------------- 8 files changed, 39 insertions(+), 56 deletions(-) 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 })