mirror of
https://github.com/corda/corda.git
synced 2025-02-25 11:03:01 +00:00
Enforce separation of Party and AnonymousParty
This commit is contained in:
parent
fa33336d38
commit
ed093cdb9d
22
core/src/main/kotlin/net/corda/core/crypto/AbstractParty.kt
Normal file
22
core/src/main/kotlin/net/corda/core/crypto/AbstractParty.kt
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package net.corda.core.crypto
|
||||||
|
|
||||||
|
import net.corda.core.contracts.PartyAndReference
|
||||||
|
import net.corda.core.serialization.OpaqueBytes
|
||||||
|
import java.security.PublicKey
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An [AbstractParty] contains the common elements of [Party] and [AnonymousParty], specifically the owning key of
|
||||||
|
* the party. In most cases [Party] or [AnonymousParty] should be used, depending on use-case.
|
||||||
|
*/
|
||||||
|
abstract class AbstractParty(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 AbstractParty && this.owningKey == other.owningKey
|
||||||
|
override fun hashCode(): Int = owningKey.hashCode()
|
||||||
|
abstract fun toAnonymous() : AnonymousParty
|
||||||
|
|
||||||
|
abstract fun ref(bytes: OpaqueBytes): PartyAndReference
|
||||||
|
fun ref(vararg bytes: Byte) = ref(OpaqueBytes.of(*bytes))
|
||||||
|
}
|
@ -8,18 +8,14 @@ import java.security.PublicKey
|
|||||||
* The [AnonymousParty] class contains enough information to uniquely identify a [Party] while excluding private
|
* 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.
|
* information such as name. It is intended to represent a party on the distributed ledger.
|
||||||
*/
|
*/
|
||||||
open class AnonymousParty(val owningKey: CompositeKey) {
|
class AnonymousParty(owningKey: CompositeKey) : AbstractParty(owningKey) {
|
||||||
/** A helper constructor that converts the given [PublicKey] in to a [CompositeKey] with a single node */
|
/** A helper constructor that converts the given [PublicKey] in to a [CompositeKey] with a single node */
|
||||||
constructor(owningKey: PublicKey) : this(owningKey.composite)
|
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()
|
|
||||||
open fun toAnonymous() : AnonymousParty = this
|
|
||||||
// Use the key as the bulk of the toString(), but include a human readable identifier as well, so that [Party]
|
// 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
|
// can put in the key and actual name
|
||||||
override fun toString() = "${owningKey.toBase58String()} <Anonymous>"
|
override fun toString() = "${owningKey.toBase58String()} <Anonymous>"
|
||||||
|
|
||||||
fun ref(bytes: OpaqueBytes) = PartyAndReference(this, bytes)
|
override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this, bytes)
|
||||||
fun ref(vararg bytes: Byte) = ref(OpaqueBytes.of(*bytes))
|
override fun toAnonymous() = this
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
|
import net.corda.core.contracts.PartyAndReference
|
||||||
|
import net.corda.core.serialization.OpaqueBytes
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9,7 +11,7 @@ import java.security.PublicKey
|
|||||||
* cryptographic public key primitives into a tree structure.
|
* cryptographic public key primitives into a tree structure.
|
||||||
*
|
*
|
||||||
* For example: Alice has two key pairs (pub1/priv1 and pub2/priv2), and wants to be able to sign transactions with either of them.
|
* For example: Alice has two key pairs (pub1/priv1 and pub2/priv2), and wants to be able to sign transactions with either of them.
|
||||||
* Her advertised [Party] then has a legal [name] "Alice" and an [owingKey] "pub1 or pub2".
|
* Her advertised [Party] then has a legal [name] "Alice" and an [owningKey] "pub1 or pub2".
|
||||||
*
|
*
|
||||||
* [Party] is also used for service identities. E.g. Alice may also be running an interest rate oracle on her Corda node,
|
* [Party] is also used for service identities. E.g. Alice may also be running an interest rate oracle on her Corda node,
|
||||||
* which requires a separate signing key (and an identifying name). Services can also be distributed – run by a coordinated
|
* which requires a separate signing key (and an identifying name). Services can also be distributed – run by a coordinated
|
||||||
@ -20,9 +22,11 @@ import java.security.PublicKey
|
|||||||
*
|
*
|
||||||
* @see CompositeKey
|
* @see CompositeKey
|
||||||
*/
|
*/
|
||||||
class Party(val name: String, owningKey: CompositeKey) : AnonymousParty(owningKey) {
|
class Party(val name: String, owningKey: CompositeKey) : AbstractParty(owningKey) {
|
||||||
/** A helper constructor that converts the given [PublicKey] in to a [CompositeKey] with a single node */
|
/** 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)
|
constructor(name: String, owningKey: PublicKey) : this(name, owningKey.composite)
|
||||||
override fun toAnonymous(): AnonymousParty = AnonymousParty(owningKey)
|
override fun toAnonymous(): AnonymousParty = AnonymousParty(owningKey)
|
||||||
override fun toString() = "${owningKey.toBase58String()} (${name})"
|
override fun toString() = "${owningKey.toBase58String()} (${name})"
|
||||||
|
|
||||||
|
override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this.toAnonymous(), bytes)
|
||||||
}
|
}
|
@ -197,7 +197,7 @@ interface VaultService {
|
|||||||
fun generateSpend(tx: TransactionBuilder,
|
fun generateSpend(tx: TransactionBuilder,
|
||||||
amount: Amount<Currency>,
|
amount: Amount<Currency>,
|
||||||
to: CompositeKey,
|
to: CompositeKey,
|
||||||
onlyFromParties: Set<AnonymousParty>? = null): Pair<TransactionBuilder, List<CompositeKey>>
|
onlyFromParties: Set<AbstractParty>? = null): Pair<TransactionBuilder, List<CompositeKey>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return [ContractState]s of a given [Contract] type and list of [Vault.StateStatus]
|
* Return [ContractState]s of a given [Contract] type and list of [Vault.StateStatus]
|
||||||
@ -216,7 +216,7 @@ inline fun <reified T : LinearState> VaultService.linearHeadsOfType() =
|
|||||||
states(setOf(T::class.java), EnumSet.of(Vault.StateStatus.UNCONSUMED))
|
states(setOf(T::class.java), EnumSet.of(Vault.StateStatus.UNCONSUMED))
|
||||||
.associateBy { it.state.data.linearId }.mapValues { it.value }
|
.associateBy { it.state.data.linearId }.mapValues { it.value }
|
||||||
|
|
||||||
inline fun <reified T : DealState> VaultService.dealsWith(party: AnonymousParty) = linearHeadsOfType<T>().values.filter {
|
inline fun <reified T : DealState> VaultService.dealsWith(party: AbstractParty) = linearHeadsOfType<T>().values.filter {
|
||||||
it.state.data.parties.any { it == party }
|
it.state.data.parties.any { it == party }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ object TwoPartyDealFlow {
|
|||||||
// And add a request for timestamping: it may be that none of the contracts need this! But it can't hurt
|
// And add a request for timestamping: it may be that none of the contracts need this! But it can't hurt
|
||||||
// to have one.
|
// to have one.
|
||||||
ptx.setTime(serviceHub.clock.instant(), 30.seconds)
|
ptx.setTime(serviceHub.clock.instant(), 30.seconds)
|
||||||
return Pair(ptx, arrayListOf(deal.parties.single { it == serviceHub.myInfo.legalIdentity }.owningKey))
|
return Pair(ptx, arrayListOf(deal.parties.single { it == serviceHub.myInfo.legalIdentity as AbstractParty }.owningKey))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,9 @@ class PartyTest {
|
|||||||
val differentKey = entropyToKeyPair(BigInteger.valueOf(7201702L)).public.composite
|
val differentKey = entropyToKeyPair(BigInteger.valueOf(7201702L)).public.composite
|
||||||
val anonymousParty = AnonymousParty(key)
|
val anonymousParty = AnonymousParty(key)
|
||||||
val party = Party("test key", key)
|
val party = Party("test key", key)
|
||||||
assertEquals(party, anonymousParty)
|
assertEquals<AbstractParty>(party, anonymousParty)
|
||||||
assertEquals(anonymousParty, party)
|
assertEquals<AbstractParty>(anonymousParty, party)
|
||||||
assertNotEquals(AnonymousParty(differentKey), anonymousParty)
|
assertNotEquals<AbstractParty>(AnonymousParty(differentKey), anonymousParty)
|
||||||
assertNotEquals(AnonymousParty(differentKey), party)
|
assertNotEquals<AbstractParty>(AnonymousParty(differentKey), party)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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.ownedBy(owner: CompositeKey) = copy(owner = owner)
|
||||||
fun Cash.State.issuedBy(party: AnonymousParty) = copy(amount = Amount(amount.quantity, amount.token.copy(issuer = amount.token.issuer.copy(party = party.toAnonymous()))))
|
fun Cash.State.issuedBy(party: AbstractParty) = copy(amount = Amount(amount.quantity, amount.token.copy(issuer = amount.token.issuer.copy(party = party.toAnonymous()))))
|
||||||
fun Cash.State.issuedBy(deposit: PartyAndReference) = copy(amount = Amount(amount.quantity, amount.token.copy(issuer = deposit)))
|
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)))
|
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.`owned by`(owner: CompositeKey) = ownedBy(owner)
|
||||||
infix fun Cash.State.`issued by`(party: AnonymousParty) = issuedBy(party)
|
infix fun Cash.State.`issued by`(party: AbstractParty) = issuedBy(party)
|
||||||
infix fun Cash.State.`issued by`(deposit: PartyAndReference) = issuedBy(deposit)
|
infix fun Cash.State.`issued by`(deposit: PartyAndReference) = issuedBy(deposit)
|
||||||
infix fun Cash.State.`with deposit`(deposit: PartyAndReference): Cash.State = withDeposit(deposit)
|
infix fun Cash.State.`with deposit`(deposit: PartyAndReference): Cash.State = withDeposit(deposit)
|
||||||
|
|
||||||
|
@ -463,7 +463,7 @@ class Obligation<P> : Contract {
|
|||||||
* Puts together an issuance transaction for the specified amount that starts out being owned by the given pubkey.
|
* Puts together an issuance transaction for the specified amount that starts out being owned by the given pubkey.
|
||||||
*/
|
*/
|
||||||
fun generateIssue(tx: TransactionBuilder,
|
fun generateIssue(tx: TransactionBuilder,
|
||||||
obligor: AnonymousParty,
|
obligor: AbstractParty,
|
||||||
issuanceDef: Terms<P>,
|
issuanceDef: Terms<P>,
|
||||||
pennies: Long,
|
pennies: Long,
|
||||||
beneficiary: CompositeKey,
|
beneficiary: CompositeKey,
|
||||||
@ -707,9 +707,9 @@ fun <P> Iterable<ContractState>.sumObligationsOrZero(issuanceDef: Issued<Obligat
|
|||||||
= filterIsInstance<Obligation.State<P>>().filter { it.lifecycle == Obligation.Lifecycle.NORMAL }.map { it.amount }.sumOrZero(issuanceDef)
|
= filterIsInstance<Obligation.State<P>>().filter { it.lifecycle == Obligation.Lifecycle.NORMAL }.map { it.amount }.sumOrZero(issuanceDef)
|
||||||
|
|
||||||
infix fun <T> Obligation.State<T>.at(dueBefore: Instant) = copy(template = template.copy(dueBefore = dueBefore))
|
infix fun <T> Obligation.State<T>.at(dueBefore: Instant) = copy(template = template.copy(dueBefore = dueBefore))
|
||||||
infix fun <T> Obligation.State<T>.between(parties: Pair<AnonymousParty, CompositeKey>) = copy(obligor = parties.first.toAnonymous(), beneficiary = parties.second)
|
infix fun <T> Obligation.State<T>.between(parties: Pair<AbstractParty, CompositeKey>) = copy(obligor = parties.first.toAnonymous(), beneficiary = parties.second)
|
||||||
infix fun <T> Obligation.State<T>.`owned by`(owner: CompositeKey) = copy(beneficiary = owner)
|
infix fun <T> Obligation.State<T>.`owned by`(owner: CompositeKey) = copy(beneficiary = owner)
|
||||||
infix fun <T> Obligation.State<T>.`issued by`(party: AnonymousParty) = copy(obligor = party.toAnonymous())
|
infix fun <T> Obligation.State<T>.`issued by`(party: AbstractParty) = copy(obligor = party.toAnonymous())
|
||||||
// For Java users:
|
// For Java users:
|
||||||
@Suppress("unused") fun <T> Obligation.State<T>.ownedBy(owner: CompositeKey) = copy(beneficiary = owner)
|
@Suppress("unused") fun <T> Obligation.State<T>.ownedBy(owner: CompositeKey) = copy(beneficiary = owner)
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import net.corda.core.contracts.Contract
|
|||||||
import net.corda.core.contracts.DealState
|
import net.corda.core.contracts.DealState
|
||||||
import net.corda.core.contracts.TransactionForContract
|
import net.corda.core.contracts.TransactionForContract
|
||||||
import net.corda.core.contracts.UniqueIdentifier
|
import net.corda.core.contracts.UniqueIdentifier
|
||||||
|
import net.corda.core.crypto.AnonymousParty
|
||||||
import net.corda.core.crypto.CompositeKey
|
import net.corda.core.crypto.CompositeKey
|
||||||
import net.corda.core.crypto.Party
|
import net.corda.core.crypto.Party
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
@ -20,10 +21,11 @@ class DummyDealContract: Contract {
|
|||||||
override val participants: List<CompositeKey> = listOf(),
|
override val participants: List<CompositeKey> = listOf(),
|
||||||
override val linearId: UniqueIdentifier = UniqueIdentifier(),
|
override val linearId: UniqueIdentifier = UniqueIdentifier(),
|
||||||
override val ref: String,
|
override val ref: String,
|
||||||
override val parties: List<Party> = listOf()) : DealState {
|
override val parties: List<AnonymousParty> = listOf()) : DealState {
|
||||||
override fun isRelevant(ourKeys: Set<PublicKey>): Boolean {
|
override fun isRelevant(ourKeys: Set<PublicKey>): Boolean {
|
||||||
return participants.any { it.containsAny(ourKeys) }
|
return participants.any { it.containsAny(ourKeys) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateAgreement(notary: Party): TransactionBuilder {
|
override fun generateAgreement(notary: Party): TransactionBuilder {
|
||||||
throw UnsupportedOperationException("not implemented")
|
throw UnsupportedOperationException("not implemented")
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ class CashTests {
|
|||||||
assertTrue(tx.inputs.isEmpty())
|
assertTrue(tx.inputs.isEmpty())
|
||||||
val s = tx.outputs[0].data as Cash.State
|
val s = tx.outputs[0].data as Cash.State
|
||||||
assertEquals(100.DOLLARS `issued by` MINI_CORP.ref(12, 34), s.amount)
|
assertEquals(100.DOLLARS `issued by` MINI_CORP.ref(12, 34), s.amount)
|
||||||
assertEquals(MINI_CORP, s.amount.token.issuer.party)
|
assertEquals(MINI_CORP as AbstractParty, s.amount.token.issuer.party)
|
||||||
assertEquals(DUMMY_PUBKEY_1, s.owner)
|
assertEquals(DUMMY_PUBKEY_1, s.owner)
|
||||||
assertTrue(tx.commands[0].value is Cash.Commands.Issue)
|
assertTrue(tx.commands[0].value is Cash.Commands.Issue)
|
||||||
assertEquals(MINI_CORP_PUBKEY, tx.commands[0].signers[0])
|
assertEquals(MINI_CORP_PUBKEY, tx.commands[0].signers[0])
|
||||||
|
@ -7,6 +7,7 @@ import net.corda.contracts.asset.Cash
|
|||||||
import net.corda.core.ThreadBox
|
import net.corda.core.ThreadBox
|
||||||
import net.corda.core.bufferUntilSubscribed
|
import net.corda.core.bufferUntilSubscribed
|
||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
|
import net.corda.core.crypto.AbstractParty
|
||||||
import net.corda.core.crypto.AnonymousParty
|
import net.corda.core.crypto.AnonymousParty
|
||||||
import net.corda.core.crypto.CompositeKey
|
import net.corda.core.crypto.CompositeKey
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
@ -222,7 +223,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P
|
|||||||
override fun generateSpend(tx: TransactionBuilder,
|
override fun generateSpend(tx: TransactionBuilder,
|
||||||
amount: Amount<Currency>,
|
amount: Amount<Currency>,
|
||||||
to: CompositeKey,
|
to: CompositeKey,
|
||||||
onlyFromParties: Set<AnonymousParty>?): Pair<TransactionBuilder, List<CompositeKey>> {
|
onlyFromParties: Set<AbstractParty>?): Pair<TransactionBuilder, List<CompositeKey>> {
|
||||||
// Discussion
|
// Discussion
|
||||||
//
|
//
|
||||||
// This code is analogous to the Wallet.send() set of methods in bitcoinj, and has the same general outline.
|
// This code is analogous to the Wallet.send() set of methods in bitcoinj, and has the same general outline.
|
||||||
|
@ -2,7 +2,7 @@ package net.corda.irs.flows
|
|||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.core.contracts.DealState
|
import net.corda.core.contracts.DealState
|
||||||
import net.corda.core.crypto.AnonymousParty
|
import net.corda.core.crypto.AbstractParty
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.node.CordaPluginRegistry
|
import net.corda.core.node.CordaPluginRegistry
|
||||||
import net.corda.core.node.PluginServiceHub
|
import net.corda.core.node.PluginServiceHub
|
||||||
@ -78,7 +78,7 @@ object AutoOfferFlow {
|
|||||||
return stx
|
return stx
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T: AnonymousParty> notUs(parties: List<T>): List<T> {
|
private fun <T: AbstractParty> notUs(parties: List<T>): List<T> {
|
||||||
val notUsParties: MutableList<T> = arrayListOf()
|
val notUsParties: MutableList<T> = arrayListOf()
|
||||||
for (party in parties) {
|
for (party in parties) {
|
||||||
if (serviceHub.myInfo.legalIdentity != party) {
|
if (serviceHub.myInfo.legalIdentity != party) {
|
||||||
|
@ -4,7 +4,7 @@ import com.opengamma.strata.basics.currency.MultiCurrencyAmount
|
|||||||
import net.corda.core.contracts.DealState
|
import net.corda.core.contracts.DealState
|
||||||
import net.corda.core.contracts.StateAndRef
|
import net.corda.core.contracts.StateAndRef
|
||||||
import net.corda.core.contracts.filterStatesOfType
|
import net.corda.core.contracts.filterStatesOfType
|
||||||
import net.corda.core.crypto.AnonymousParty
|
import net.corda.core.crypto.AbstractParty
|
||||||
import net.corda.core.crypto.CompositeKey
|
import net.corda.core.crypto.CompositeKey
|
||||||
import net.corda.core.crypto.Party
|
import net.corda.core.crypto.Party
|
||||||
import net.corda.core.getOrThrow
|
import net.corda.core.getOrThrow
|
||||||
@ -34,7 +34,7 @@ class PortfolioApi(val rpc: CordaRPCOps) {
|
|||||||
private val ownParty: Party get() = rpc.nodeIdentity().legalIdentity
|
private val ownParty: Party get() = rpc.nodeIdentity().legalIdentity
|
||||||
private val portfolioUtils = PortfolioApiUtils(ownParty)
|
private val portfolioUtils = PortfolioApiUtils(ownParty)
|
||||||
|
|
||||||
private inline fun <reified T : DealState> dealsWith(party: AnonymousParty): List<StateAndRef<T>> {
|
private inline fun <reified T : DealState> dealsWith(party: AbstractParty): List<StateAndRef<T>> {
|
||||||
return rpc.vaultAndUpdates().first.filterStatesOfType<T>().filter { it.state.data.parties.any { it == party } }
|
return rpc.vaultAndUpdates().first.filterStatesOfType<T>().filter { it.state.data.parties.any { it == party } }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ class PortfolioApi(val rpc: CordaRPCOps) {
|
|||||||
return withParty(partyName) { party ->
|
return withParty(partyName) { party ->
|
||||||
withPortfolio(party) { state ->
|
withPortfolio(party) { state ->
|
||||||
if (state.valuation != null) {
|
if (state.valuation != null) {
|
||||||
val isValuer = state.valuer as AnonymousParty == ownParty
|
val isValuer = state.valuer as AbstractParty == ownParty
|
||||||
val rawMtm = state.valuation.presentValues.map {
|
val rawMtm = state.valuation.presentValues.map {
|
||||||
it.value.amounts.first().amount
|
it.value.amounts.first().amount
|
||||||
}.reduce { a, b -> a + b }
|
}.reduce { a, b -> a + b }
|
||||||
|
@ -5,6 +5,7 @@ import com.opengamma.strata.product.swap.IborRateCalculation
|
|||||||
import com.opengamma.strata.product.swap.RateCalculationSwapLeg
|
import com.opengamma.strata.product.swap.RateCalculationSwapLeg
|
||||||
import com.opengamma.strata.product.swap.SwapLegType
|
import com.opengamma.strata.product.swap.SwapLegType
|
||||||
import net.corda.core.contracts.hash
|
import net.corda.core.contracts.hash
|
||||||
|
import net.corda.core.crypto.AbstractParty
|
||||||
import net.corda.core.crypto.Party
|
import net.corda.core.crypto.Party
|
||||||
import net.corda.vega.contracts.IRSState
|
import net.corda.vega.contracts.IRSState
|
||||||
import net.corda.vega.contracts.PortfolioState
|
import net.corda.vega.contracts.PortfolioState
|
||||||
@ -122,7 +123,7 @@ class PortfolioApiUtils(private val ownParty: Party) {
|
|||||||
val ref: String)
|
val ref: String)
|
||||||
|
|
||||||
fun createTradeView(state: IRSState): TradeView {
|
fun createTradeView(state: IRSState): TradeView {
|
||||||
val trade = if (state.buyer == ownParty) state.swap.toFloatingLeg() else state.swap.toFloatingLeg()
|
val trade = if (state.buyer == ownParty as AbstractParty) state.swap.toFloatingLeg() else state.swap.toFloatingLeg()
|
||||||
val fixedLeg = trade.product.legs.first { it.type == SwapLegType.FIXED } as RateCalculationSwapLeg
|
val fixedLeg = trade.product.legs.first { it.type == SwapLegType.FIXED } as RateCalculationSwapLeg
|
||||||
val floatingLeg = trade.product.legs.first { it.type != SwapLegType.FIXED } as RateCalculationSwapLeg
|
val floatingLeg = trade.product.legs.first { it.type != SwapLegType.FIXED } as RateCalculationSwapLeg
|
||||||
val fixedRate = fixedLeg.calculation as FixedRateCalculation
|
val fixedRate = fixedLeg.calculation as FixedRateCalculation
|
||||||
|
@ -9,7 +9,7 @@ import com.opengamma.strata.product.common.BuySell
|
|||||||
import com.opengamma.strata.product.swap.SwapTrade
|
import com.opengamma.strata.product.swap.SwapTrade
|
||||||
import com.opengamma.strata.product.swap.type.FixedIborSwapConvention
|
import com.opengamma.strata.product.swap.type.FixedIborSwapConvention
|
||||||
import com.opengamma.strata.product.swap.type.FixedIborSwapConventions
|
import com.opengamma.strata.product.swap.type.FixedIborSwapConventions
|
||||||
import net.corda.core.crypto.AnonymousParty
|
import net.corda.core.crypto.AbstractParty
|
||||||
import net.corda.core.crypto.CompositeKey
|
import net.corda.core.crypto.CompositeKey
|
||||||
import net.corda.core.crypto.Party
|
import net.corda.core.crypto.Party
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
@ -48,7 +48,7 @@ data class SwapData(
|
|||||||
val notional: BigDecimal,
|
val notional: BigDecimal,
|
||||||
val fixedRate: BigDecimal) {
|
val fixedRate: BigDecimal) {
|
||||||
|
|
||||||
fun getLegForParty(party: AnonymousParty): Leg {
|
fun getLegForParty(party: AbstractParty): Leg {
|
||||||
return if (party == buyer.second) FixedLeg(notional) else FloatingLeg(notional)
|
return if (party == buyer.second) FixedLeg(notional) else FloatingLeg(notional)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import net.corda.core.contracts.Amount
|
|||||||
import net.corda.core.contracts.Issued
|
import net.corda.core.contracts.Issued
|
||||||
import net.corda.core.contracts.PartyAndReference
|
import net.corda.core.contracts.PartyAndReference
|
||||||
import net.corda.core.contracts.withoutIssuer
|
import net.corda.core.contracts.withoutIssuer
|
||||||
|
import net.corda.core.crypto.AbstractParty
|
||||||
import net.corda.core.crypto.Party
|
import net.corda.core.crypto.Party
|
||||||
import net.corda.core.flows.FlowException
|
import net.corda.core.flows.FlowException
|
||||||
import net.corda.core.getOrThrow
|
import net.corda.core.getOrThrow
|
||||||
@ -199,7 +200,7 @@ class NewTransaction : Fragment() {
|
|||||||
)
|
)
|
||||||
availableAmount.textProperty()
|
availableAmount.textProperty()
|
||||||
.bind(Bindings.createStringBinding({
|
.bind(Bindings.createStringBinding({
|
||||||
val filteredCash = cash.filtered { it.token.issuer.party == issuer.value && it.token.product == currencyChoiceBox.value }
|
val filteredCash = cash.filtered { it.token.issuer.party as AbstractParty == issuer.value && it.token.product == currencyChoiceBox.value }
|
||||||
.map { it.withoutIssuer().quantity }
|
.map { it.withoutIssuer().quantity }
|
||||||
"${filteredCash.sum()} ${currencyChoiceBox.value?.currencyCode} Available"
|
"${filteredCash.sum()} ${currencyChoiceBox.value?.currencyCode} Available"
|
||||||
}, arrayOf(currencyChoiceBox.valueProperty(), issuerChoiceBox.valueProperty())))
|
}, arrayOf(currencyChoiceBox.valueProperty(), issuerChoiceBox.valueProperty())))
|
||||||
|
@ -6,6 +6,7 @@ import net.corda.contracts.asset.Cash
|
|||||||
import net.corda.core.contracts.Issued
|
import net.corda.core.contracts.Issued
|
||||||
import net.corda.core.contracts.PartyAndReference
|
import net.corda.core.contracts.PartyAndReference
|
||||||
import net.corda.core.contracts.USD
|
import net.corda.core.contracts.USD
|
||||||
|
import net.corda.core.crypto.AbstractParty
|
||||||
import net.corda.core.crypto.AnonymousParty
|
import net.corda.core.crypto.AnonymousParty
|
||||||
import net.corda.core.flows.FlowException
|
import net.corda.core.flows.FlowException
|
||||||
import net.corda.core.getOrThrow
|
import net.corda.core.getOrThrow
|
||||||
@ -50,7 +51,7 @@ data class CrossCashCommand(
|
|||||||
* Map from node to (map from issuer to USD quantity)
|
* Map from node to (map from issuer to USD quantity)
|
||||||
*/
|
*/
|
||||||
data class CrossCashState(
|
data class CrossCashState(
|
||||||
val nodeVaults: Map<AnonymousParty, Map<AnonymousParty, Long>>,
|
val nodeVaults: Map<AbstractParty, Map<AbstractParty, Long>>,
|
||||||
|
|
||||||
// node -> (notifying node -> [(issuer, amount)])
|
// node -> (notifying node -> [(issuer, amount)])
|
||||||
// This map holds the queues that encode the non-determinism of how tx notifications arrive in the background.
|
// This map holds the queues that encode the non-determinism of how tx notifications arrive in the background.
|
||||||
@ -68,20 +69,20 @@ data class CrossCashState(
|
|||||||
// requires more concurrent code which is conceptually also more complex than the current design.
|
// 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
|
// TODO: Alternative: We may possibly reduce the complexity of the search even further using some form of
|
||||||
// knapsack instead of the naive search
|
// knapsack instead of the naive search
|
||||||
val diffQueues: Map<AnonymousParty, Map<AnonymousParty, List<Pair<AnonymousParty, Long>>>>
|
val diffQueues: Map<AbstractParty, Map<AbstractParty, List<Pair<AbstractParty, Long>>>>
|
||||||
) {
|
) {
|
||||||
fun copyVaults(): HashMap<AnonymousParty, HashMap<AnonymousParty, Long>> {
|
fun copyVaults(): HashMap<AbstractParty, HashMap<AbstractParty, Long>> {
|
||||||
val newNodeVaults = HashMap<AnonymousParty, HashMap<AnonymousParty, Long>>()
|
val newNodeVaults = HashMap<AbstractParty, HashMap<AbstractParty, Long>>()
|
||||||
for ((key, value) in nodeVaults) {
|
for ((key, value) in nodeVaults) {
|
||||||
newNodeVaults[key] = HashMap(value)
|
newNodeVaults[key] = HashMap(value)
|
||||||
}
|
}
|
||||||
return newNodeVaults
|
return newNodeVaults
|
||||||
}
|
}
|
||||||
|
|
||||||
fun copyQueues(): HashMap<AnonymousParty, HashMap<AnonymousParty, ArrayList<Pair<AnonymousParty, Long>>>> {
|
fun copyQueues(): HashMap<AbstractParty, HashMap<AbstractParty, ArrayList<Pair<AbstractParty, Long>>>> {
|
||||||
val newDiffQueues = HashMap<AnonymousParty, HashMap<AnonymousParty, ArrayList<Pair<AnonymousParty, Long>>>>()
|
val newDiffQueues = HashMap<AbstractParty, HashMap<AbstractParty, ArrayList<Pair<AbstractParty, Long>>>>()
|
||||||
for ((node, queues) in diffQueues) {
|
for ((node, queues) in diffQueues) {
|
||||||
val newQueues = HashMap<AnonymousParty, ArrayList<Pair<AnonymousParty, Long>>>()
|
val newQueues = HashMap<AbstractParty, ArrayList<Pair<AbstractParty, Long>>>()
|
||||||
for ((sender, value) in queues) {
|
for ((sender, value) in queues) {
|
||||||
newQueues[sender] = ArrayList(value)
|
newQueues[sender] = ArrayList(value)
|
||||||
}
|
}
|
||||||
@ -217,9 +218,9 @@ val crossCashTest = LoadTest<CrossCashCommand, CrossCashState>(
|
|||||||
|
|
||||||
gatherRemoteState = { previousState ->
|
gatherRemoteState = { previousState ->
|
||||||
log.info("Reifying state...")
|
log.info("Reifying state...")
|
||||||
val currentNodeVaults = HashMap<AnonymousParty, HashMap<AnonymousParty, Long>>()
|
val currentNodeVaults = HashMap<AbstractParty, HashMap<AbstractParty, Long>>()
|
||||||
simpleNodes.forEach {
|
simpleNodes.forEach {
|
||||||
val quantities = HashMap<AnonymousParty, Long>()
|
val quantities = HashMap<AbstractParty, Long>()
|
||||||
val vault = it.connection.proxy.vaultAndUpdates().first
|
val vault = it.connection.proxy.vaultAndUpdates().first
|
||||||
vault.forEach {
|
vault.forEach {
|
||||||
val state = it.state.data
|
val state = it.state.data
|
||||||
@ -231,7 +232,7 @@ val crossCashTest = LoadTest<CrossCashCommand, CrossCashState>(
|
|||||||
currentNodeVaults.put(it.info.legalIdentity, quantities)
|
currentNodeVaults.put(it.info.legalIdentity, quantities)
|
||||||
}
|
}
|
||||||
val (consistentVaults, diffQueues) = if (previousState == null) {
|
val (consistentVaults, diffQueues) = if (previousState == null) {
|
||||||
Pair(currentNodeVaults, mapOf<AnonymousParty, Map<AnonymousParty, List<Pair<AnonymousParty, Long>>>>())
|
Pair(currentNodeVaults, mapOf<AbstractParty, Map<AbstractParty, List<Pair<AbstractParty, Long>>>>())
|
||||||
} else {
|
} else {
|
||||||
log.info("${previousState.diffQueues.values.sumBy { it.values.sumBy { it.size } }} txs in limbo")
|
log.info("${previousState.diffQueues.values.sumBy { it.values.sumBy { it.size } }} txs in limbo")
|
||||||
val newDiffQueues = previousState.copyQueues()
|
val newDiffQueues = previousState.copyQueues()
|
||||||
@ -249,12 +250,12 @@ val crossCashTest = LoadTest<CrossCashCommand, CrossCashState>(
|
|||||||
"\nActual gathered state:\n${CrossCashState(currentNodeVaults, mapOf())}"
|
"\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
|
// 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<AnonymousParty, Map<AnonymousParty, List<Pair<AnonymousParty, Long>>>>())
|
return@LoadTest CrossCashState(currentNodeVaults, mapOf<AbstractParty, Map<AbstractParty, List<Pair<AbstractParty, Long>>>>())
|
||||||
}
|
}
|
||||||
if (matches.size > 1) {
|
if (matches.size > 1) {
|
||||||
log.warn("Multiple predicted states match the remote state")
|
log.warn("Multiple predicted states match the remote state")
|
||||||
}
|
}
|
||||||
val minimumMatches = matches.fold<Map<AnonymousParty, Int>, HashMap<AnonymousParty, Int>?>(null) { minimum, next ->
|
val minimumMatches = matches.fold<Map<AbstractParty, Int>, HashMap<AbstractParty, Int>?>(null) { minimum, next ->
|
||||||
if (minimum == null) {
|
if (minimum == null) {
|
||||||
HashMap(next)
|
HashMap(next)
|
||||||
} else {
|
} else {
|
||||||
|
@ -6,7 +6,7 @@ import net.corda.client.mock.pickOne
|
|||||||
import net.corda.client.mock.replicatePoisson
|
import net.corda.client.mock.replicatePoisson
|
||||||
import net.corda.contracts.asset.Cash
|
import net.corda.contracts.asset.Cash
|
||||||
import net.corda.core.contracts.USD
|
import net.corda.core.contracts.USD
|
||||||
import net.corda.core.crypto.AnonymousParty
|
import net.corda.core.crypto.AbstractParty
|
||||||
import net.corda.core.crypto.Party
|
import net.corda.core.crypto.Party
|
||||||
import net.corda.core.flows.FlowException
|
import net.corda.core.flows.FlowException
|
||||||
import net.corda.core.getOrThrow
|
import net.corda.core.getOrThrow
|
||||||
@ -28,9 +28,9 @@ data class SelfIssueCommand(
|
|||||||
)
|
)
|
||||||
|
|
||||||
data class SelfIssueState(
|
data class SelfIssueState(
|
||||||
val vaultsSelfIssued: Map<AnonymousParty, Long>
|
val vaultsSelfIssued: Map<AbstractParty, Long>
|
||||||
) {
|
) {
|
||||||
fun copyVaults(): HashMap<AnonymousParty, Long> {
|
fun copyVaults(): HashMap<AbstractParty, Long> {
|
||||||
return HashMap(vaultsSelfIssued)
|
return HashMap(vaultsSelfIssued)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,14 +72,14 @@ val selfIssueTest = LoadTest<SelfIssueCommand, SelfIssueState>(
|
|||||||
},
|
},
|
||||||
|
|
||||||
gatherRemoteState = { previousState ->
|
gatherRemoteState = { previousState ->
|
||||||
val selfIssueVaults = HashMap<AnonymousParty, Long>()
|
val selfIssueVaults = HashMap<AbstractParty, Long>()
|
||||||
simpleNodes.forEach { node ->
|
simpleNodes.forEach { node ->
|
||||||
val vault = node.connection.proxy.vaultAndUpdates().first
|
val vault = node.connection.proxy.vaultAndUpdates().first
|
||||||
vault.forEach {
|
vault.forEach {
|
||||||
val state = it.state.data
|
val state = it.state.data
|
||||||
if (state is Cash.State) {
|
if (state is Cash.State) {
|
||||||
val issuer = state.amount.token.issuer.party
|
val issuer = state.amount.token.issuer.party
|
||||||
if (issuer == node.info.legalIdentity as AnonymousParty) {
|
if (issuer == node.info.legalIdentity as AbstractParty) {
|
||||||
selfIssueVaults.put(issuer, (selfIssueVaults[issuer] ?: 0L) + state.amount.quantity)
|
selfIssueVaults.put(issuer, (selfIssueVaults[issuer] ?: 0L) + state.amount.quantity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user