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.
This commit is contained in:
Ross Nicoll
2017-05-19 11:22:47 +01:00
committed by GitHub
parent d288fcc979
commit 794ce03958
8 changed files with 39 additions and 56 deletions

View File

@ -4,7 +4,6 @@ import net.corda.core.identity.Party
import net.corda.core.utilities.ALICE import net.corda.core.utilities.ALICE
import net.corda.core.utilities.BOB import net.corda.core.utilities.BOB
import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.DUMMY_NOTARY
import net.corda.testing.MOCK_IDENTITY_SERVICE
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@ -17,7 +16,6 @@ class TxKeyFlowUtilitiesTests {
@Before @Before
fun before() { fun before() {
net = MockNetwork(false) net = MockNetwork(false)
net.identities += MOCK_IDENTITY_SERVICE.identities
} }
@Test @Test

View File

@ -4,11 +4,11 @@ import com.google.common.util.concurrent.ListenableFuture
import net.corda.contracts.testing.calculateRandomlySizedAmounts import net.corda.contracts.testing.calculateRandomlySizedAmounts
import net.corda.core.contracts.Amount import net.corda.core.contracts.Amount
import net.corda.core.contracts.DOLLARS import net.corda.core.contracts.DOLLARS
import net.corda.core.contracts.PartyAndReference
import net.corda.core.contracts.currency import net.corda.core.contracts.currency
import net.corda.core.flows.FlowException import net.corda.core.flows.FlowException
import net.corda.core.flows.FlowStateMachine import net.corda.core.flows.FlowStateMachine
import net.corda.core.getOrThrow import net.corda.core.getOrThrow
import net.corda.core.identity.Party
import net.corda.core.map import net.corda.core.map
import net.corda.core.serialization.OpaqueBytes import net.corda.core.serialization.OpaqueBytes
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
@ -40,13 +40,14 @@ class IssuerFlowTest {
bankClientNode = net.createPartyNode(notaryNode.info.address, MEGA_CORP.name) bankClientNode = net.createPartyNode(notaryNode.info.address, MEGA_CORP.name)
// using default IssueTo Party Reference // using default IssueTo Party Reference
val issueToPartyAndRef = bankClientNode.info.legalIdentity.ref(OpaqueBytes.of(123)) val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankClientNode, 1000000.DOLLARS,
val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankClientNode, 1000000.DOLLARS, issueToPartyAndRef) bankClientNode.info.legalIdentity, OpaqueBytes.of(123))
assertEquals(issuerResult.get(), issuer.get().resultFuture.get()) assertEquals(issuerResult.get(), issuer.get().resultFuture.get())
// try to issue an amount of a restricted currency // try to issue an amount of a restricted currency
assertFailsWith<FlowException> { assertFailsWith<FlowException> {
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() bankOfCordaNode.stop()
@ -62,8 +63,8 @@ class IssuerFlowTest {
bankOfCordaNode = net.createPartyNode(notaryNode.info.address, BOC.name) bankOfCordaNode = net.createPartyNode(notaryNode.info.address, BOC.name)
// using default IssueTo Party Reference // using default IssueTo Party Reference
val issueToPartyAndRef = bankOfCordaNode.info.legalIdentity.ref(OpaqueBytes.of(123)) val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankOfCordaNode, 1000000.DOLLARS,
val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankOfCordaNode, 1000000.DOLLARS, issueToPartyAndRef) bankOfCordaNode.info.legalIdentity, OpaqueBytes.of(123))
assertEquals(issuerResult.get(), issuer.get().resultFuture.get()) assertEquals(issuerResult.get(), issuer.get().resultFuture.get())
bankOfCordaNode.stop() bankOfCordaNode.stop()
@ -79,14 +80,12 @@ class IssuerFlowTest {
bankOfCordaNode = net.createPartyNode(notaryNode.info.address, BOC.name) bankOfCordaNode = net.createPartyNode(notaryNode.info.address, BOC.name)
bankClientNode = net.createPartyNode(notaryNode.info.address, MEGA_CORP.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 // this test exercises the Cashflow issue and move subflows to ensure consistent spending of issued states
val amount = 10000.DOLLARS val amount = 10000.DOLLARS
val amounts = calculateRandomlySizedAmounts(10000.DOLLARS, 10, 10, Random()) val amounts = calculateRandomlySizedAmounts(10000.DOLLARS, 10, 10, Random())
val handles = amounts.map { pennies -> 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 { handles.forEach {
require(it.issueRequestResult.get() is SignedTransaction) require(it.issueRequestResult.get() is SignedTransaction)
@ -98,13 +97,14 @@ class IssuerFlowTest {
} }
private fun runIssuerAndIssueRequester(issuerNode: MockNode, issueToNode: MockNode, private fun runIssuerAndIssueRequester(issuerNode: MockNode, issueToNode: MockNode,
amount: Amount<Currency>, issueToPartyAndRef: PartyAndReference): RunResult { amount: Amount<Currency>,
val resolvedIssuerParty = issuerNode.services.identityService.partyFromAnonymous(issueToPartyAndRef) ?: throw IllegalStateException() party: Party, ref: OpaqueBytes): RunResult {
val issueToPartyAndRef = party.ref(ref)
val issuerFuture = issuerNode.initiateSingleShotFlow(IssuerFlow.IssuanceRequester::class) { _ -> val issuerFuture = issuerNode.initiateSingleShotFlow(IssuerFlow.IssuanceRequester::class) { _ ->
IssuerFlow.Issuer(resolvedIssuerParty) IssuerFlow.Issuer(party)
}.map { it.stateMachine } }.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 val issueRequestResultFuture = issueToNode.services.startFlow(issueRequest).resultFuture
return IssuerFlowTest.RunResult(issuerFuture, issueRequestResultFuture) return IssuerFlowTest.RunResult(issuerFuture, issueRequestResultFuture)

View File

@ -20,9 +20,13 @@ import javax.annotation.concurrent.ThreadSafe
/** /**
* Simple identity service which caches parties and provides functionality for efficient lookup. * 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 @ThreadSafe
class InMemoryIdentityService : SingletonSerializeAsToken(), IdentityService { class InMemoryIdentityService(identities: Iterable<Party> = emptySet(),
certPaths: Map<AnonymousParty, CertPath> = emptyMap()) : SingletonSerializeAsToken(), IdentityService {
companion object { companion object {
private val log = loggerFor<InMemoryIdentityService>() private val log = loggerFor<InMemoryIdentityService>()
} }
@ -31,6 +35,12 @@ class InMemoryIdentityService : SingletonSerializeAsToken(), IdentityService {
private val principalToParties = ConcurrentHashMap<X500Name, Party>() private val principalToParties = ConcurrentHashMap<X500Name, Party>()
private val partyToPath = ConcurrentHashMap<AnonymousParty, CertPath>() private val partyToPath = ConcurrentHashMap<AnonymousParty, CertPath>()
init {
keyToParties.putAll(identities.associateBy { it.owningKey } )
principalToParties.putAll(identities.associateBy { it.name })
partyToPath.putAll(certPaths)
}
override fun registerIdentity(party: Party) { override fun registerIdentity(party: Party) {
log.trace { "Registering identity $party" } log.trace { "Registering identity $party" }
keyToParties[party.owningKey] = party keyToParties[party.owningKey] = party

View File

@ -70,7 +70,6 @@ class TwoPartyTradeFlowTests {
@Before @Before
fun before() { fun before() {
net = MockNetwork(false) net = MockNetwork(false)
net.identities += MOCK_IDENTITY_SERVICE.identities
LogHelper.setLevel("platform.trade", "core.contract.TransactionGroup", "recordingmap") LogHelper.setLevel("platform.trade", "core.contract.TransactionGroup", "recordingmap")
} }
@ -501,6 +500,8 @@ class TwoPartyTradeFlowTests {
serviceHub.legalIdentityKey)) serviceHub.legalIdentityKey))
} }
sellerNode.services.identityService.registerIdentity(buyerNode.info.legalIdentity)
buyerNode.services.identityService.registerIdentity(sellerNode.info.legalIdentity)
val buyerFuture = buyerNode.initiateSingleShotFlow(SellerRunnerFlow::class) { otherParty -> val buyerFuture = buyerNode.initiateSingleShotFlow(SellerRunnerFlow::class) { otherParty ->
Buyer(otherParty, notaryNode.info.notaryIdentity, 1000.DOLLARS, CommercialPaper.State::class.java) Buyer(otherParty, notaryNode.info.notaryIdentity, 1000.DOLLARS, CommercialPaper.State::class.java)
}.map { it.stateMachine } }.map { it.stateMachine }

View File

@ -1,6 +1,7 @@
package net.corda.irs.simulation package net.corda.irs.simulation
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.google.common.util.concurrent.FutureCallback import com.google.common.util.concurrent.FutureCallback
import com.google.common.util.concurrent.Futures 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.FlowLogic
import net.corda.core.flows.FlowStateMachine import net.corda.core.flows.FlowStateMachine
import net.corda.core.flows.InitiatingFlow import net.corda.core.flows.InitiatingFlow
import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.map import net.corda.core.map
import net.corda.core.node.services.linearHeadsOfType 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.flows.TwoPartyDealFlow.Instigator
import net.corda.irs.contract.InterestRateSwap import net.corda.irs.contract.InterestRateSwap
import net.corda.jackson.JacksonSupport import net.corda.jackson.JacksonSupport
import net.corda.node.services.identity.InMemoryIdentityService
import net.corda.node.utilities.transaction import net.corda.node.utilities.transaction
import net.corda.testing.initiateSingleShotFlow import net.corda.testing.initiateSingleShotFlow
import net.corda.testing.node.InMemoryMessagingNetwork import net.corda.testing.node.InMemoryMessagingNetwork
import net.corda.testing.node.MockIdentityService
import java.security.PublicKey import java.security.PublicKey
import java.time.LocalDate import java.time.LocalDate
import java.util.* 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. * 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) { 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 { init {
currentDateAndTime = LocalDate.of(2016, 3, 8).atStartOfDay() currentDateAndTime = LocalDate.of(2016, 3, 8).atStartOfDay()
@ -47,6 +47,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
override fun startMainSimulation(): ListenableFuture<Unit> { override fun startMainSimulation(): ListenableFuture<Unit> {
val future = SettableFuture.create<Unit>() val future = SettableFuture.create<Unit>()
om = JacksonSupport.createInMemoryMapper(InMemoryIdentityService((banks + regulators + networkMap).map { it.info.legalIdentity }))
startIRSDealBetween(0, 1).success { startIRSDealBetween(0, 1).success {
// Next iteration is a pause. // Next iteration is a pause.

View File

@ -11,6 +11,7 @@ import net.corda.core.flows.FlowLogic
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.node.VersionInfo import net.corda.core.node.VersionInfo
import net.corda.core.node.services.IdentityService
import net.corda.core.serialization.OpaqueBytes import net.corda.core.serialization.OpaqueBytes
import net.corda.core.toFuture import net.corda.core.toFuture
import net.corda.core.transactions.TransactionBuilder 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.AbstractNode
import net.corda.node.internal.NetworkMapInfo import net.corda.node.internal.NetworkMapInfo
import net.corda.node.services.config.* 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.FlowStateMachineImpl
import net.corda.node.services.statemachine.StateMachineManager import net.corda.node.services.statemachine.StateMachineManager
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.nodeapi.config.SSLConfiguration import net.corda.nodeapi.config.SSLConfiguration
import net.corda.testing.node.MockIdentityService
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestDataSourceProperties import net.corda.testing.node.makeTestDataSourceProperties
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x500.X500NameBuilder import org.bouncycastle.asn1.x500.X500NameBuilder
import org.bouncycastle.asn1.x500.style.BCStyle import org.bouncycastle.asn1.x500.style.BCStyle
import java.net.ServerSocket
import java.net.URL import java.net.URL
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path 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<KeyPair> get() = listOf(MEGA_CORP_KEY, MINI_CORP_KEY, ALICE_KEY, BOB_KEY, DUMMY_NOTARY_KEY) val ALL_TEST_KEYS: List<KeyPair> 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") val MOCK_VERSION_INFO = VersionInfo(1, "Mock release", "Mock revision", "Mock Vendor")

View File

@ -20,6 +20,7 @@ import net.corda.core.utilities.loggerFor
import net.corda.node.internal.AbstractNode import net.corda.node.internal.AbstractNode
import net.corda.node.internal.ServiceFlowInfo import net.corda.node.internal.ServiceFlowInfo
import net.corda.node.services.config.NodeConfiguration 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.keys.E2ETestKeyManagementService
import net.corda.node.services.messaging.MessagingService import net.corda.node.services.messaging.MessagingService
import net.corda.node.services.network.InMemoryNetworkMapService import net.corda.node.services.network.InMemoryNetworkMapService
@ -166,7 +167,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
.getOrThrow() .getOrThrow()
} }
override fun makeIdentityService() = MockIdentityService(mockNet.identities) override fun makeIdentityService() = InMemoryIdentityService(mockNet.identities)
override fun makeVaultService(dataSourceProperties: Properties): VaultService = NodeVaultService(services, dataSourceProperties) override fun makeVaultService(dataSourceProperties: Properties): VaultService = NodeVaultService(services, dataSourceProperties)

View File

@ -14,6 +14,7 @@ import net.corda.core.node.services.*
import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.DUMMY_NOTARY 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.persistence.InMemoryStateMachineRecordedTransactionMappingStorage
import net.corda.node.services.schema.HibernateObserver import net.corda.node.services.schema.HibernateObserver
import net.corda.node.services.schema.NodeSchemaService import net.corda.node.services.schema.NodeSchemaService
@ -37,6 +38,7 @@ import java.security.cert.CertPath
import java.security.cert.X509Certificate import java.security.cert.X509Certificate
import java.time.Clock import java.time.Clock
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.jar.JarInputStream import java.util.jar.JarInputStream
import javax.annotation.concurrent.ThreadSafe import javax.annotation.concurrent.ThreadSafe
@ -62,7 +64,7 @@ open class MockServices(vararg val keys: KeyPair) : ServiceHub {
} }
override val storageService: TxWritableStorageService = MockStorageService() 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 keyManagementService: KeyManagementService = MockKeyManagementService(*keys)
override val vaultService: VaultService get() = throw UnsupportedOperationException() 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<Party>,
val certificates: List<Triple<AnonymousParty, Party, CertPath>> = emptyList()) : IdentityService, SingletonSerializeAsToken() {
private val keyToParties: Map<PublicKey, Party>
get() = synchronized(identities) { identities.associateBy { it.owningKey } }
private val nameToParties: Map<X500Name, Party>
get() = synchronized(identities) { identities.associateBy { it.name } }
private val anonymousToPath: Map<AnonymousParty, Pair<Party, CertPath>>
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<Party> = 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 { class MockKeyManagementService(vararg initialKeys: KeyPair) : SingletonSerializeAsToken(), KeyManagementService {
private val keyStore: MutableMap<PublicKey, PrivateKey> = initialKeys.associateByTo(HashMap(), { it.public }, { it.private }) private val keyStore: MutableMap<PublicKey, PrivateKey> = initialKeys.associateByTo(HashMap(), { it.public }, { it.private })