mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Add AnonymousParty superclass of Party
Add AnonymousParty superclass of Party in preparation for anonymising parties stored in contract states. Signed-off-by: Ross Nicoll <ross.nicoll@r3.com>
This commit is contained in:
parent
0287876987
commit
47d260625a
@ -1,6 +1,7 @@
|
||||
package net.corda.core.contracts
|
||||
|
||||
import net.corda.core.contracts.clauses.Clause
|
||||
import net.corda.core.crypto.AnonymousParty
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.crypto.SecureHash
|
||||
@ -349,8 +350,8 @@ inline fun <reified T : ContractState> Iterable<StateAndRef<ContractState>>.filt
|
||||
* Reference to something being stored or issued by a party e.g. in a vault or (more likely) on their normal
|
||||
* ledger. The reference is intended to be encrypted so it's meaningless to anyone other than the party.
|
||||
*/
|
||||
data class PartyAndReference(val party: Party, val reference: OpaqueBytes) {
|
||||
override fun toString() = "${party.name}$reference"
|
||||
data class PartyAndReference(val party: AnonymousParty, val reference: OpaqueBytes) {
|
||||
override fun toString() = "${party}$reference"
|
||||
}
|
||||
|
||||
/** Marker interface for classes that represent commands */
|
||||
|
24
core/src/main/kotlin/net/corda/core/crypto/AnonymousParty.kt
Normal file
24
core/src/main/kotlin/net/corda/core/crypto/AnonymousParty.kt
Normal file
@ -0,0 +1,24 @@
|
||||
package net.corda.core.crypto
|
||||
|
||||
import net.corda.core.contracts.PartyAndReference
|
||||
import net.corda.core.serialization.OpaqueBytes
|
||||
import java.security.PublicKey
|
||||
|
||||
/**
|
||||
* The [AnonymousParty] class contains enough information to uniquely identify a [Party] while excluding private
|
||||
* information such as name. It is intended to represent a party on the distributed ledger.
|
||||
*/
|
||||
open class AnonymousParty(val owningKey: CompositeKey) {
|
||||
/** A helper constructor that converts the given [PublicKey] in to a [CompositeKey] with a single node */
|
||||
constructor(owningKey: PublicKey) : this(owningKey.composite)
|
||||
|
||||
/** Anonymised parties do not include any detail apart from owning key, so equality is dependent solely on the key */
|
||||
override fun equals(other: Any?): Boolean = other is AnonymousParty && this.owningKey == other.owningKey
|
||||
override fun hashCode(): Int = owningKey.hashCode()
|
||||
// Use the key as the bulk of the toString(), but include a human readable identifier as well, so that [Party]
|
||||
// can put in the key and actual name
|
||||
override fun toString() = "${owningKey.toBase58String()} <Anonymous>"
|
||||
|
||||
fun ref(bytes: OpaqueBytes) = PartyAndReference(this, bytes)
|
||||
fun ref(vararg bytes: Byte) = ref(OpaqueBytes.of(*bytes))
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
package net.corda.core.crypto
|
||||
|
||||
import net.corda.core.contracts.PartyAndReference
|
||||
import net.corda.core.serialization.OpaqueBytes
|
||||
import java.security.PublicKey
|
||||
|
||||
/**
|
||||
@ -22,15 +20,8 @@ import java.security.PublicKey
|
||||
*
|
||||
* @see CompositeKey
|
||||
*/
|
||||
class Party(val name: String, val owningKey: CompositeKey) {
|
||||
class Party(val name: String, owningKey: CompositeKey) : AnonymousParty(owningKey) {
|
||||
/** A helper constructor that converts the given [PublicKey] in to a [CompositeKey] with a single node */
|
||||
constructor(name: String, owningKey: PublicKey) : this(name, owningKey.composite)
|
||||
|
||||
/** Anonymised parties do not include any detail apart from owning key, so equality is dependent solely on the key */
|
||||
override fun equals(other: Any?): Boolean = other is Party && this.owningKey == other.owningKey
|
||||
override fun hashCode(): Int = owningKey.hashCode()
|
||||
override fun toString() = name
|
||||
|
||||
fun ref(bytes: OpaqueBytes) = PartyAndReference(this, bytes)
|
||||
fun ref(vararg bytes: Byte) = ref(OpaqueBytes.of(*bytes))
|
||||
override fun toString() = "${owningKey.toBase58String()} (name)"
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package net.corda.core.node.services
|
||||
|
||||
import net.corda.core.contracts.PartyAndReference
|
||||
import net.corda.core.crypto.AnonymousParty
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
import net.corda.core.crypto.Party
|
||||
|
||||
@ -10,6 +12,7 @@ import net.corda.core.crypto.Party
|
||||
*/
|
||||
interface IdentityService {
|
||||
fun registerIdentity(party: Party)
|
||||
|
||||
/**
|
||||
* Get all identities known to the service. This is expensive, and [partyFromKey] or [partyFromName] should be
|
||||
* used in preference where possible.
|
||||
@ -22,4 +25,7 @@ interface IdentityService {
|
||||
|
||||
fun partyFromKey(key: CompositeKey): Party?
|
||||
fun partyFromName(name: String): Party?
|
||||
|
||||
fun partyFromAnonymous(party: AnonymousParty): Party?
|
||||
fun partyFromAnonymous(partyRef: PartyAndReference) = partyFromAnonymous(partyRef.party)
|
||||
}
|
||||
|
@ -2,10 +2,7 @@ package net.corda.core.node.services
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.toStringShort
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.toFuture
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
@ -198,7 +195,7 @@ interface VaultService {
|
||||
fun generateSpend(tx: TransactionBuilder,
|
||||
amount: Amount<Currency>,
|
||||
to: CompositeKey,
|
||||
onlyFromParties: Set<Party>? = null): Pair<TransactionBuilder, List<CompositeKey>>
|
||||
onlyFromParties: Set<AnonymousParty>? = null): Pair<TransactionBuilder, List<CompositeKey>>
|
||||
}
|
||||
|
||||
inline fun <reified T : LinearState> VaultService.linearHeadsOfType() = linearHeadsOfType_(T::class.java)
|
||||
|
Binary file not shown.
20
core/src/test/kotlin/net/corda/core/crypto/PartyTest.kt
Normal file
20
core/src/test/kotlin/net/corda/core/crypto/PartyTest.kt
Normal file
@ -0,0 +1,20 @@
|
||||
package net.corda.core.crypto
|
||||
|
||||
import org.junit.Test
|
||||
import java.math.BigInteger
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotEquals
|
||||
|
||||
class PartyTest {
|
||||
@Test
|
||||
fun `equality`() {
|
||||
val key = entropyToKeyPair(BigInteger.valueOf(20170207L)).public.composite
|
||||
val differentKey = entropyToKeyPair(BigInteger.valueOf(7201702L)).public.composite
|
||||
val anonymousParty = AnonymousParty(key)
|
||||
val party = Party("test key", key)
|
||||
assertEquals(party, anonymousParty)
|
||||
assertEquals(anonymousParty, party)
|
||||
assertNotEquals(AnonymousParty(differentKey), anonymousParty)
|
||||
assertNotEquals(AnonymousParty(differentKey), party)
|
||||
}
|
||||
}
|
@ -87,14 +87,15 @@ Party and CompositeKey
|
||||
Entities using the network are called *parties*. Parties can sign structures using keys, and a party may have many
|
||||
keys under their control.
|
||||
|
||||
Parties may sometimes be identified pseudonymously. For example, in a transaction sent to your node as part of a
|
||||
chain of custody it is important you can convince yourself of the transaction's validity, but equally important that
|
||||
you don't learn anything about who was involved in that transaction. In these cases a public key may be present
|
||||
without any identifying information about who owns it.
|
||||
Parties can be represented either in full (including name) or pseudonymously, using the ``Party`` or ``AnonymousParty``
|
||||
classes respectively. For example, in a transaction sent to your node as part of a chain of custody it is important you
|
||||
can convince yourself of the transaction's validity, but equally important that you don't learn anything about who was
|
||||
involved in that transaction. In these cases ``AnonymousParty`` should be used, which contains a composite public key
|
||||
without any identifying information about who owns it. In contrast, for internal processing where extended details of
|
||||
a party are required, the ``Party`` class should be used. The identity service provides functionality for resolving
|
||||
anonymous parties to full parties.
|
||||
|
||||
Identities of parties involved in signing a transaction can be represented simply by a ``CompositeKey``, or by further
|
||||
information (such as name) using the ``Party`` class. An ``AuthenticatedObject`` represents an object (like a command)
|
||||
that has been signed by a set of parties.
|
||||
An ``AuthenticatedObject`` represents an object (like a command) that has been signed by a set of parties.
|
||||
|
||||
.. note:: These types are provisional and will change significantly in future as the identity framework becomes more fleshed out.
|
||||
|
||||
|
@ -3,6 +3,13 @@ Release notes
|
||||
|
||||
Here are brief summaries of what's changed between each snapshot release.
|
||||
|
||||
Milestone 9
|
||||
-----------
|
||||
|
||||
* API:
|
||||
|
||||
* Pseudonymous ``AnonymousParty`` class added as a superclass of ``Party``.
|
||||
|
||||
Milestone 8
|
||||
-----------
|
||||
|
||||
|
@ -192,12 +192,12 @@ fun Iterable<ContractState>.sumCashOrZero(currency: Issued<Currency>): Amount<Is
|
||||
}
|
||||
|
||||
fun Cash.State.ownedBy(owner: CompositeKey) = copy(owner = owner)
|
||||
fun Cash.State.issuedBy(party: Party) = copy(amount = Amount(amount.quantity, amount.token.copy(issuer = amount.token.issuer.copy(party = party))))
|
||||
fun Cash.State.issuedBy(party: AnonymousParty) = copy(amount = Amount(amount.quantity, amount.token.copy(issuer = amount.token.issuer.copy(party = party))))
|
||||
fun Cash.State.issuedBy(deposit: PartyAndReference) = copy(amount = Amount(amount.quantity, amount.token.copy(issuer = deposit)))
|
||||
fun Cash.State.withDeposit(deposit: PartyAndReference): Cash.State = copy(amount = amount.copy(token = amount.token.copy(issuer = deposit)))
|
||||
|
||||
infix fun Cash.State.`owned by`(owner: CompositeKey) = ownedBy(owner)
|
||||
infix fun Cash.State.`issued by`(party: Party) = issuedBy(party)
|
||||
infix fun Cash.State.`issued by`(party: AnonymousParty) = issuedBy(party)
|
||||
infix fun Cash.State.`issued by`(deposit: PartyAndReference) = issuedBy(deposit)
|
||||
infix fun Cash.State.`with deposit`(deposit: PartyAndReference): Cash.State = withDeposit(deposit)
|
||||
|
||||
|
@ -3,6 +3,7 @@ package net.corda.flows
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.contracts.asset.Cash
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.AnonymousParty
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.crypto.keys
|
||||
import net.corda.core.crypto.toStringShort
|
||||
|
@ -12,7 +12,6 @@ import net.corda.core.map
|
||||
import net.corda.core.serialization.OpaqueBytes
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.DUMMY_NOTARY
|
||||
import net.corda.core.utilities.DUMMY_NOTARY_KEY
|
||||
import net.corda.flows.IssuerFlow.IssuanceRequester
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.node.MockNetwork
|
||||
@ -54,11 +53,12 @@ class IssuerFlowTest {
|
||||
}
|
||||
|
||||
private fun runIssuerAndIssueRequester(amount: Amount<Currency>, issueToPartyAndRef: PartyAndReference) : RunResult {
|
||||
val resolvedIssuerParty = bankOfCordaNode.services.identityService.partyFromAnonymous(issueToPartyAndRef) ?: throw IllegalStateException()
|
||||
val issuerFuture = bankOfCordaNode.initiateSingleShotFlow(IssuerFlow.IssuanceRequester::class) {
|
||||
otherParty -> IssuerFlow.Issuer(issueToPartyAndRef.party)
|
||||
otherParty -> IssuerFlow.Issuer(resolvedIssuerParty)
|
||||
}.map { it.stateMachine }
|
||||
|
||||
val issueRequest = IssuanceRequester(amount, issueToPartyAndRef.party, issueToPartyAndRef.reference, bankOfCordaNode.info.legalIdentity)
|
||||
val issueRequest = IssuanceRequester(amount, resolvedIssuerParty, issueToPartyAndRef.reference, bankOfCordaNode.info.legalIdentity)
|
||||
val issueRequestResultFuture = bankClientNode.services.startFlow(issueRequest).resultFuture
|
||||
|
||||
return IssuerFlowTest.RunResult(issuerFuture, issueRequestResultFuture)
|
||||
|
@ -1,5 +1,7 @@
|
||||
package net.corda.node.services.identity
|
||||
|
||||
import net.corda.core.contracts.PartyAndReference
|
||||
import net.corda.core.crypto.AnonymousParty
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.node.services.IdentityService
|
||||
@ -26,4 +28,11 @@ class InMemoryIdentityService() : SingletonSerializeAsToken(), IdentityService {
|
||||
|
||||
override fun partyFromKey(key: CompositeKey): Party? = keyToParties[key]
|
||||
override fun partyFromName(name: String): Party? = nameToParties[name]
|
||||
override fun partyFromAnonymous(party: AnonymousParty): Party? {
|
||||
return if (party is Party)
|
||||
party
|
||||
else
|
||||
partyFromKey(party.owningKey)
|
||||
}
|
||||
override fun partyFromAnonymous(partyRef: PartyAndReference) = partyFromAnonymous(partyRef.party)
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import net.corda.contracts.asset.Cash
|
||||
import net.corda.core.ThreadBox
|
||||
import net.corda.core.bufferUntilSubscribed
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.AnonymousParty
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.node.services.Vault
|
||||
@ -198,7 +198,7 @@ class NodeVaultService(private val services: ServiceHub) : SingletonSerializeAsT
|
||||
override fun generateSpend(tx: TransactionBuilder,
|
||||
amount: Amount<Currency>,
|
||||
to: CompositeKey,
|
||||
onlyFromParties: Set<Party>?): Pair<TransactionBuilder, List<CompositeKey>> {
|
||||
onlyFromParties: Set<AnonymousParty>?): Pair<TransactionBuilder, List<CompositeKey>> {
|
||||
// Discussion
|
||||
//
|
||||
// This code is analogous to the Wallet.send() set of methods in bitcoinj, and has the same general outline.
|
||||
|
@ -4,10 +4,7 @@ import net.corda.contracts.CommercialPaper
|
||||
import net.corda.contracts.asset.*
|
||||
import net.corda.contracts.testing.fillWithSomeTestCash
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.composite
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.days
|
||||
import net.corda.core.flows.FlowStateMachine
|
||||
import net.corda.core.flows.StateMachineRunId
|
||||
@ -490,7 +487,7 @@ class TwoPartyTradeFlowTests {
|
||||
private fun LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter>.fillUpForBuyer(
|
||||
withError: Boolean,
|
||||
owner: CompositeKey,
|
||||
issuer: Party,
|
||||
issuer: AnonymousParty,
|
||||
notary: Party): Pair<Vault, List<WireTransaction>> {
|
||||
val interimOwnerKey = MEGA_CORP_PUBKEY
|
||||
// Bob (Buyer) has some cash he got from the Bank of Elbonia, Alice (Seller) has some commercial paper she
|
||||
|
@ -2,6 +2,7 @@ package net.corda.testing.node
|
||||
|
||||
import kotlinx.support.jdk8.collections.putIfAbsent
|
||||
import net.corda.core.contracts.Attachment
|
||||
import net.corda.core.contracts.PartyAndReference
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.FlowStateMachine
|
||||
@ -73,6 +74,8 @@ class MockIdentityService(val identities: List<Party>) : IdentityService, Single
|
||||
|
||||
override fun registerIdentity(party: Party) { throw UnsupportedOperationException() }
|
||||
override fun getAllIdentities(): Iterable<Party> = ArrayList(keyToParties.values)
|
||||
override fun partyFromAnonymous(party: AnonymousParty): Party? = keyToParties[party.owningKey]
|
||||
override fun partyFromAnonymous(partyRef: PartyAndReference): Party? = partyFromAnonymous(partyRef.party)
|
||||
override fun partyFromKey(key: CompositeKey): Party? = keyToParties[key]
|
||||
override fun partyFromName(name: String): Party? = nameToParties[name]
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import net.corda.contracts.asset.Cash
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.contracts.StateAndRef
|
||||
import net.corda.core.contracts.withoutIssuer
|
||||
import net.corda.core.crypto.AnonymousParty
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.explorer.formatters.AmountFormatter
|
||||
import net.corda.explorer.identicon.identicon
|
||||
@ -84,7 +85,7 @@ class CashViewer : CordaView("Cash") {
|
||||
*/
|
||||
sealed class ViewerNode(val equivAmount: ObservableValue<out Amount<Currency>>,
|
||||
val states: ObservableList<StateAndRef<Cash.State>>) {
|
||||
class IssuerNode(val issuer: Party,
|
||||
class IssuerNode(val issuer: AnonymousParty,
|
||||
sumEquivAmount: ObservableValue<out Amount<Currency>>,
|
||||
states: ObservableList<StateAndRef<Cash.State>>) : ViewerNode(sumEquivAmount, states)
|
||||
|
||||
|
@ -6,6 +6,7 @@ import net.corda.contracts.asset.Cash
|
||||
import net.corda.core.contracts.Issued
|
||||
import net.corda.core.contracts.PartyAndReference
|
||||
import net.corda.core.contracts.USD
|
||||
import net.corda.core.crypto.AnonymousParty
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.flows.FlowException
|
||||
import net.corda.core.getOrThrow
|
||||
@ -49,7 +50,7 @@ data class CrossCashCommand(
|
||||
* Map from node to (map from issuer to USD quantity)
|
||||
*/
|
||||
data class CrossCashState(
|
||||
val nodeVaults: Map<Party, Map<Party, Long>>,
|
||||
val nodeVaults: Map<AnonymousParty, Map<AnonymousParty, Long>>,
|
||||
|
||||
// node -> (notifying node -> [(issuer, amount)])
|
||||
// This map holds the queues that encode the non-determinism of how tx notifications arrive in the background.
|
||||
@ -67,20 +68,20 @@ data class CrossCashState(
|
||||
// requires more concurrent code which is conceptually also more complex than the current design.
|
||||
// TODO: Alternative: We may possibly reduce the complexity of the search even further using some form of
|
||||
// knapsack instead of the naive search
|
||||
val diffQueues: Map<Party, Map<Party, List<Pair<Party, Long>>>>
|
||||
val diffQueues: Map<AnonymousParty, Map<AnonymousParty, List<Pair<AnonymousParty, Long>>>>
|
||||
) {
|
||||
fun copyVaults(): HashMap<Party, HashMap<Party, Long>> {
|
||||
val newNodeVaults = HashMap<Party, HashMap<Party, Long>>()
|
||||
fun copyVaults(): HashMap<AnonymousParty, HashMap<AnonymousParty, Long>> {
|
||||
val newNodeVaults = HashMap<AnonymousParty, HashMap<AnonymousParty, Long>>()
|
||||
for ((key, value) in nodeVaults) {
|
||||
newNodeVaults[key] = HashMap(value)
|
||||
}
|
||||
return newNodeVaults
|
||||
}
|
||||
|
||||
fun copyQueues(): HashMap<Party, HashMap<Party, ArrayList<Pair<Party, Long>>>> {
|
||||
val newDiffQueues = HashMap<Party, HashMap<Party, ArrayList<Pair<Party, Long>>>>()
|
||||
fun copyQueues(): HashMap<AnonymousParty, HashMap<AnonymousParty, ArrayList<Pair<AnonymousParty, Long>>>> {
|
||||
val newDiffQueues = HashMap<AnonymousParty, HashMap<AnonymousParty, ArrayList<Pair<AnonymousParty, Long>>>>()
|
||||
for ((node, queues) in diffQueues) {
|
||||
val newQueues = HashMap<Party, ArrayList<Pair<Party, Long>>>()
|
||||
val newQueues = HashMap<AnonymousParty, ArrayList<Pair<AnonymousParty, Long>>>()
|
||||
for ((sender, value) in queues) {
|
||||
newQueues[sender] = ArrayList(value)
|
||||
}
|
||||
@ -216,9 +217,9 @@ val crossCashTest = LoadTest<CrossCashCommand, CrossCashState>(
|
||||
|
||||
gatherRemoteState = { previousState ->
|
||||
log.info("Reifying state...")
|
||||
val currentNodeVaults = HashMap<Party, HashMap<Party, Long>>()
|
||||
val currentNodeVaults = HashMap<AnonymousParty, HashMap<AnonymousParty, Long>>()
|
||||
simpleNodes.forEach {
|
||||
val quantities = HashMap<Party, Long>()
|
||||
val quantities = HashMap<AnonymousParty, Long>()
|
||||
val vault = it.connection.proxy.vaultAndUpdates().first
|
||||
vault.forEach {
|
||||
val state = it.state.data
|
||||
@ -230,7 +231,7 @@ val crossCashTest = LoadTest<CrossCashCommand, CrossCashState>(
|
||||
currentNodeVaults.put(it.info.legalIdentity, quantities)
|
||||
}
|
||||
val (consistentVaults, diffQueues) = if (previousState == null) {
|
||||
Pair(currentNodeVaults, mapOf<Party, Map<Party, List<Pair<Party, Long>>>>())
|
||||
Pair(currentNodeVaults, mapOf<AnonymousParty, Map<AnonymousParty, List<Pair<AnonymousParty, Long>>>>())
|
||||
} else {
|
||||
log.info("${previousState.diffQueues.values.sumBy { it.values.sumBy { it.size } }} txs in limbo")
|
||||
val newDiffQueues = previousState.copyQueues()
|
||||
@ -248,12 +249,12 @@ val crossCashTest = LoadTest<CrossCashCommand, CrossCashState>(
|
||||
"\nActual gathered state:\n${CrossCashState(currentNodeVaults, mapOf())}"
|
||||
)
|
||||
// TODO We should terminate here with an exception, we cannot carry on as we have an inconsistent model. We carry on currently because we always diverge due to notarisation failures
|
||||
return@LoadTest CrossCashState(currentNodeVaults, mapOf<Party, Map<Party, List<Pair<Party, Long>>>>())
|
||||
return@LoadTest CrossCashState(currentNodeVaults, mapOf<AnonymousParty, Map<AnonymousParty, List<Pair<AnonymousParty, Long>>>>())
|
||||
}
|
||||
if (matches.size > 1) {
|
||||
log.warn("Multiple predicted states match the remote state")
|
||||
}
|
||||
val minimumMatches = matches.fold<Map<Party, Int>, HashMap<Party, Int>?>(null) { minimum, next ->
|
||||
val minimumMatches = matches.fold<Map<AnonymousParty, Int>, HashMap<AnonymousParty, Int>?>(null) { minimum, next ->
|
||||
if (minimum == null) {
|
||||
HashMap(next)
|
||||
} else {
|
||||
|
@ -5,6 +5,7 @@ import net.corda.client.mock.generateAmount
|
||||
import net.corda.client.mock.pickOne
|
||||
import net.corda.core.contracts.Issued
|
||||
import net.corda.core.contracts.PartyAndReference
|
||||
import net.corda.core.crypto.AnonymousParty
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.serialization.OpaqueBytes
|
||||
import net.corda.flows.CashCommand
|
||||
@ -27,7 +28,7 @@ fun generateIssue(
|
||||
fun generateMove(
|
||||
max: Long,
|
||||
currency: Currency,
|
||||
issuer: Party,
|
||||
issuer: AnonymousParty,
|
||||
possibleRecipients: List<Party>
|
||||
): Generator<CashCommand.PayCash> {
|
||||
return generateAmount(1, max, Generator.pure(Issued(PartyAndReference(issuer, OpaqueBytes.of(0)), currency))).combine(
|
||||
|
@ -6,6 +6,7 @@ import net.corda.client.mock.pickOne
|
||||
import net.corda.client.mock.replicatePoisson
|
||||
import net.corda.contracts.asset.Cash
|
||||
import net.corda.core.contracts.USD
|
||||
import net.corda.core.crypto.AnonymousParty
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.flows.FlowException
|
||||
import net.corda.core.getOrThrow
|
||||
@ -26,9 +27,9 @@ data class SelfIssueCommand(
|
||||
)
|
||||
|
||||
data class SelfIssueState(
|
||||
val vaultsSelfIssued: Map<Party, Long>
|
||||
val vaultsSelfIssued: Map<AnonymousParty, Long>
|
||||
) {
|
||||
fun copyVaults(): HashMap<Party, Long> {
|
||||
fun copyVaults(): HashMap<AnonymousParty, Long> {
|
||||
return HashMap(vaultsSelfIssued)
|
||||
}
|
||||
}
|
||||
@ -70,7 +71,7 @@ val selfIssueTest = LoadTest<SelfIssueCommand, SelfIssueState>(
|
||||
},
|
||||
|
||||
gatherRemoteState = { previousState ->
|
||||
val selfIssueVaults = HashMap<Party, Long>()
|
||||
val selfIssueVaults = HashMap<AnonymousParty, Long>()
|
||||
simpleNodes.forEach { node ->
|
||||
val vault = node.connection.proxy.vaultAndUpdates().first
|
||||
vault.forEach {
|
||||
|
Loading…
Reference in New Issue
Block a user