diff --git a/client/jackson/src/main/kotlin/net/corda/jackson/JacksonSupport.kt b/client/jackson/src/main/kotlin/net/corda/jackson/JacksonSupport.kt index 361313dbe3..83fd59088f 100644 --- a/client/jackson/src/main/kotlin/net/corda/jackson/JacksonSupport.kt +++ b/client/jackson/src/main/kotlin/net/corda/jackson/JacksonSupport.kt @@ -10,6 +10,7 @@ import com.fasterxml.jackson.module.kotlin.KotlinModule import net.corda.core.contracts.Amount import net.corda.core.contracts.BusinessCalendar import net.corda.core.crypto.* +import net.corda.core.identity.AbstractParty import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import net.corda.core.messaging.CordaRPCOps @@ -66,6 +67,7 @@ object JacksonSupport { addDeserializer(AnonymousParty::class.java, AnonymousPartyDeserializer) addSerializer(Party::class.java, PartySerializer) addDeserializer(Party::class.java, PartyDeserializer) + addDeserializer(AbstractParty::class.java, PartyDeserializer) addSerializer(BigDecimal::class.java, ToStringSerializer) addDeserializer(BigDecimal::class.java, NumberDeserializers.BigDecimalDeserializer()) addSerializer(SecureHash::class.java, SecureHashSerializer) @@ -160,8 +162,16 @@ object JacksonSupport { } val mapper = parser.codec as PartyObjectMapper - val principal = X500Name(parser.text) - return mapper.partyFromPrincipal(principal) ?: throw JsonParseException(parser, "Could not find a Party with name ${principal}") + // TODO: We should probably have a better specified way of identifying X.500 names vs keys + // Base58 keys never include an equals character, while X.500 names always will, so we use that to determine + // how to parse the content + return if (parser.text.contains("=")) { + val principal = X500Name(parser.text) + mapper.partyFromPrincipal(principal) ?: throw JsonParseException(parser, "Could not find a Party with name ${principal}") + } else { + val key = parsePublicKeyBase58(parser.text) + mapper.partyFromKey(key) ?: throw JsonParseException(parser, "Could not find a Party with key ${key.toStringShort()}") + } } } diff --git a/core/src/main/kotlin/net/corda/core/contracts/ContractsDSL.kt b/core/src/main/kotlin/net/corda/core/contracts/ContractsDSL.kt index 5b62e342f9..0737f9d498 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/ContractsDSL.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/ContractsDSL.kt @@ -115,7 +115,7 @@ inline fun verifyMoveCommand(inputs: List() val keysThatSigned = command.signers.toSet() requireThat { diff --git a/core/src/main/kotlin/net/corda/core/contracts/DummyContract.kt b/core/src/main/kotlin/net/corda/core/contracts/DummyContract.kt index f7116222ac..31e85f859c 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/DummyContract.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/DummyContract.kt @@ -1,9 +1,9 @@ package net.corda.core.contracts import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.transactions.TransactionBuilder -import java.security.PublicKey // The dummy contract doesn't do anything useful. It exists for testing purposes. @@ -14,12 +14,12 @@ data class DummyContract(override val legalContractReference: SecureHash = Secur val magicNumber: Int } - data class SingleOwnerState(override val magicNumber: Int = 0, override val owner: PublicKey) : OwnableState, State { + data class SingleOwnerState(override val magicNumber: Int = 0, override val owner: AbstractParty) : OwnableState, State { override val contract = DUMMY_PROGRAM_ID - override val participants: List + override val participants: List get() = listOf(owner) - override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner)) + override fun withNewOwner(newOwner: AbstractParty) = Pair(Commands.Move(), copy(owner = newOwner)) } /** @@ -28,9 +28,9 @@ data class DummyContract(override val legalContractReference: SecureHash = Secur * in a different field, however this is a good example of a contract with multiple states. */ data class MultiOwnerState(override val magicNumber: Int = 0, - val owners: List) : ContractState, State { + val owners: List) : ContractState, State { override val contract = DUMMY_PROGRAM_ID - override val participants: List get() = owners + override val participants: List get() = owners } interface Commands : CommandData { @@ -47,22 +47,22 @@ data class DummyContract(override val legalContractReference: SecureHash = Secur fun generateInitial(magicNumber: Int, notary: Party, owner: PartyAndReference, vararg otherOwners: PartyAndReference): TransactionBuilder { val owners = listOf(owner) + otherOwners return if (owners.size == 1) { - val state = SingleOwnerState(magicNumber, owners.first().party.owningKey) + val state = SingleOwnerState(magicNumber, owners.first().party) TransactionType.General.Builder(notary = notary).withItems(state, Command(Commands.Create(), owners.first().party.owningKey)) } else { - val state = MultiOwnerState(magicNumber, owners.map { it.party.owningKey }) + val state = MultiOwnerState(magicNumber, owners.map { it.party }) TransactionType.General.Builder(notary = notary).withItems(state, Command(Commands.Create(), owners.map { it.party.owningKey })) } } - fun move(prior: StateAndRef, newOwner: PublicKey) = move(listOf(prior), newOwner) - fun move(priors: List>, newOwner: PublicKey): TransactionBuilder { + fun move(prior: StateAndRef, newOwner: AbstractParty) = move(listOf(prior), newOwner) + fun move(priors: List>, newOwner: AbstractParty): TransactionBuilder { require(priors.isNotEmpty()) val priorState = priors[0].state.data val (cmd, state) = priorState.withNewOwner(newOwner) return TransactionType.General.Builder(notary = priors[0].state.notary).withItems( /* INPUTS */ *priors.toTypedArray(), - /* COMMAND */ Command(cmd, priorState.owner), + /* COMMAND */ Command(cmd, priorState.owner.owningKey), /* OUTPUT */ state ) } diff --git a/core/src/main/kotlin/net/corda/core/contracts/DummyContractV2.kt b/core/src/main/kotlin/net/corda/core/contracts/DummyContractV2.kt index 2fcc633144..a0c4386236 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/DummyContractV2.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/DummyContractV2.kt @@ -1,9 +1,9 @@ package net.corda.core.contracts import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty import net.corda.core.transactions.WireTransaction import net.corda.flows.ContractUpgradeFlow -import java.security.PublicKey // The dummy contract doesn't do anything useful. It exists for testing purposes. val DUMMY_V2_PROGRAM_ID = DummyContractV2() @@ -15,9 +15,9 @@ val DUMMY_V2_PROGRAM_ID = DummyContractV2() class DummyContractV2 : UpgradedContract { override val legacyContract = DummyContract::class.java - data class State(val magicNumber: Int = 0, val owners: List) : ContractState { + data class State(val magicNumber: Int = 0, val owners: List) : ContractState { override val contract = DUMMY_V2_PROGRAM_ID - override val participants: List = owners + override val participants: List = owners } interface Commands : CommandData { @@ -44,16 +44,16 @@ class DummyContractV2 : UpgradedContract): Pair> { + fun generateUpgradeFromV1(vararg states: StateAndRef): Pair> { val notary = states.map { it.state.notary }.single() require(states.isNotEmpty()) - val signees = states.flatMap { it.state.data.participants }.toSet() + val signees: Set = states.flatMap { it.state.data.participants }.distinct().toSet() return Pair(TransactionType.General.Builder(notary).apply { states.forEach { addInputState(it) addOutputState(upgrade(it.state.data)) - addCommand(UpgradeCommand(DUMMY_V2_PROGRAM_ID.javaClass), signees.toList()) + addCommand(UpgradeCommand(DUMMY_V2_PROGRAM_ID.javaClass), signees.map { it.owningKey }.toList()) } }.toWireTransaction(), signees) } diff --git a/core/src/main/kotlin/net/corda/core/contracts/DummyState.kt b/core/src/main/kotlin/net/corda/core/contracts/DummyState.kt index 0eb8d4555f..1498b8c379 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/DummyState.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/DummyState.kt @@ -1,12 +1,12 @@ package net.corda.core.contracts -import java.security.PublicKey +import net.corda.core.identity.AbstractParty /** * Dummy state for use in testing. Not part of any contract, not even the [DummyContract]. */ data class DummyState(val magicNumber: Int = 0) : ContractState { override val contract = DUMMY_PROGRAM_ID - override val participants: List + override val participants: List get() = emptyList() } diff --git a/core/src/main/kotlin/net/corda/core/contracts/FungibleAsset.kt b/core/src/main/kotlin/net/corda/core/contracts/FungibleAsset.kt index da4dca8a32..bf6d856d97 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/FungibleAsset.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/FungibleAsset.kt @@ -1,12 +1,8 @@ package net.corda.core.contracts -import net.corda.core.identity.Party import net.corda.core.flows.FlowException -import net.corda.core.transactions.TransactionBuilder -import net.corda.core.utilities.loggerFor -import net.corda.core.utilities.trace +import net.corda.core.identity.AbstractParty import java.security.PublicKey -import java.util.* class InsufficientBalanceException(val amountMissing: Amount<*>) : FlowException("Insufficient balance, missing $amountMissing") @@ -32,9 +28,9 @@ interface FungibleAsset : OwnableState { */ val exitKeys: Collection /** There must be a MoveCommand signed by this key to claim the amount */ - override val owner: PublicKey + override val owner: AbstractParty - fun move(newAmount: Amount>, newOwner: PublicKey): FungibleAsset + fun move(newAmount: Amount>, newOwner: AbstractParty): FungibleAsset // Just for grouping interface Commands : CommandData { diff --git a/core/src/main/kotlin/net/corda/core/contracts/Structures.kt b/core/src/main/kotlin/net/corda/core/contracts/Structures.kt index 6ea81ca9a5..3f7b7339b9 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/Structures.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/Structures.kt @@ -4,6 +4,7 @@ import net.corda.core.contracts.clauses.Clause import net.corda.core.crypto.SecureHash import net.corda.core.flows.FlowLogicRef import net.corda.core.flows.FlowLogicRefFactory +import net.corda.core.identity.AbstractParty import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import net.corda.core.node.services.ServiceType @@ -114,7 +115,7 @@ interface ContractState { * The participants list should normally be derived from the contents of the state. E.g. for [Cash] the participants * list should just contain the owner. */ - val participants: List + val participants: List } /** @@ -174,10 +175,10 @@ fun Amount>.withoutIssuer(): Amount = Amount(quantity, to */ interface OwnableState : ContractState { /** There must be a MoveCommand signed by this key to claim the amount */ - val owner: PublicKey + val owner: AbstractParty /** Copies the underlying data structure, replacing the owner field with this new value and leaving the rest alone */ - fun withNewOwner(newOwner: PublicKey): Pair + fun withNewOwner(newOwner: AbstractParty): Pair } /** Something which is scheduled to happen at a point in time */ @@ -280,7 +281,7 @@ interface DealState : LinearState { * separate process exchange certificates to ascertain identities. Thus decoupling identities from * [ContractState]s. * */ - val parties: List + val parties: List /** * Generate a partial transaction representing an agreement (command) to this deal, allowing a general @@ -343,9 +344,7 @@ inline fun Iterable>.filt * ledger. The reference is intended to be encrypted so it's meaningless to anyone other than the party. */ @CordaSerializable -data class PartyAndReference(val party: AnonymousParty, val reference: OpaqueBytes) { - constructor(party: Party, reference: OpaqueBytes) : this(party.toAnonymous(), reference) - +data class PartyAndReference(val party: AbstractParty, val reference: OpaqueBytes) { override fun toString() = "$party$reference" } diff --git a/core/src/main/kotlin/net/corda/core/contracts/TransactionTypes.kt b/core/src/main/kotlin/net/corda/core/contracts/TransactionTypes.kt index d40e3ef608..e4d343a3c6 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/TransactionTypes.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/TransactionTypes.kt @@ -148,7 +148,7 @@ sealed class TransactionType { */ class Builder(notary: Party) : TransactionBuilder(NotaryChange, notary) { override fun addInputState(stateAndRef: StateAndRef<*>) { - signers.addAll(stateAndRef.state.data.participants) + signers.addAll(stateAndRef.state.data.participants.map { it.owningKey }) super.addInputState(stateAndRef) } } @@ -171,6 +171,6 @@ sealed class TransactionType { } } - override fun getRequiredSigners(tx: LedgerTransaction) = tx.inputs.flatMap { it.state.data.participants }.toSet() + override fun getRequiredSigners(tx: LedgerTransaction) = tx.inputs.flatMap { it.state.data.participants }.map { it.owningKey }.toSet() } } diff --git a/core/src/main/kotlin/net/corda/core/crypto/CryptoUtils.kt b/core/src/main/kotlin/net/corda/core/crypto/CryptoUtils.kt index 69fe06fd43..66a4ec85ac 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/CryptoUtils.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/CryptoUtils.kt @@ -2,10 +2,11 @@ package net.corda.core.crypto +import net.corda.core.identity.AbstractParty +import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.OpaqueBytes -import net.i2p.crypto.eddsa.EdDSAPublicKey import java.math.BigInteger import java.security.* @@ -18,6 +19,8 @@ object NullPublicKey : PublicKey, Comparable { override fun toString() = "NULL_KEY" } +val NULL_PARTY = AnonymousParty(NullPublicKey) + // TODO: Clean up this duplication between Null and Dummy public key @CordaSerializable class DummyPublicKey(val s: String) : PublicKey, Comparable { diff --git a/core/src/main/kotlin/net/corda/core/identity/AbstractParty.kt b/core/src/main/kotlin/net/corda/core/identity/AbstractParty.kt index 9f90a5267a..6b285c3698 100644 --- a/core/src/main/kotlin/net/corda/core/identity/AbstractParty.kt +++ b/core/src/main/kotlin/net/corda/core/identity/AbstractParty.kt @@ -16,7 +16,6 @@ abstract class AbstractParty(val owningKey: PublicKey) { 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 nameOrNull(): X500Name? abstract fun ref(bytes: OpaqueBytes): PartyAndReference diff --git a/core/src/main/kotlin/net/corda/core/identity/AnonymousParty.kt b/core/src/main/kotlin/net/corda/core/identity/AnonymousParty.kt index 81c04846cc..dc1ec16f58 100644 --- a/core/src/main/kotlin/net/corda/core/identity/AnonymousParty.kt +++ b/core/src/main/kotlin/net/corda/core/identity/AnonymousParty.kt @@ -18,5 +18,4 @@ class AnonymousParty(owningKey: PublicKey) : AbstractParty(owningKey) { override fun nameOrNull(): X500Name? = null override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this, bytes) - override fun toAnonymous() = this } \ No newline at end of file diff --git a/core/src/main/kotlin/net/corda/core/identity/Party.kt b/core/src/main/kotlin/net/corda/core/identity/Party.kt index 8c951c18ac..b834d38330 100644 --- a/core/src/main/kotlin/net/corda/core/identity/Party.kt +++ b/core/src/main/kotlin/net/corda/core/identity/Party.kt @@ -29,9 +29,8 @@ import java.security.PublicKey // TODO: Remove "open" from [Party] once deprecated crypto.Party class is removed open class Party(val name: X500Name, owningKey: PublicKey) : AbstractParty(owningKey) { constructor(certAndKey: CertificateAndKey) : this(X500Name(certAndKey.certificate.subjectDN.name), certAndKey.keyPair.public) - override fun toAnonymous(): AnonymousParty = AnonymousParty(owningKey) override fun toString() = "${owningKey.toBase58String()} ($name)" override fun nameOrNull(): X500Name? = name - override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this.toAnonymous(), bytes) + override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this, bytes) } diff --git a/core/src/main/kotlin/net/corda/core/node/services/IdentityService.kt b/core/src/main/kotlin/net/corda/core/node/services/IdentityService.kt index 78e00368af..4dafa52ef0 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/IdentityService.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/IdentityService.kt @@ -1,6 +1,7 @@ package net.corda.core.node.services import net.corda.core.contracts.PartyAndReference +import net.corda.core.identity.AbstractParty import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import org.bouncycastle.asn1.x500.X500Name @@ -54,7 +55,7 @@ interface IdentityService { fun partyFromName(name: String): Party? fun partyFromX500Name(principal: X500Name): Party? - fun partyFromAnonymous(party: AnonymousParty): Party? + fun partyFromAnonymous(party: AbstractParty): Party? fun partyFromAnonymous(partyRef: PartyAndReference) = partyFromAnonymous(partyRef.party) /** diff --git a/core/src/main/kotlin/net/corda/core/node/services/Services.kt b/core/src/main/kotlin/net/corda/core/node/services/Services.kt index c29f534a2e..5e56b6c567 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/Services.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/Services.kt @@ -3,7 +3,9 @@ package net.corda.core.node.services import co.paralleluniverse.fibers.Suspendable import com.google.common.util.concurrent.ListenableFuture import net.corda.core.contracts.* -import net.corda.core.crypto.* +import net.corda.core.crypto.CompositeKey +import net.corda.core.crypto.SecureHash +import net.corda.core.crypto.toStringShort import net.corda.core.flows.FlowException import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party @@ -286,7 +288,7 @@ interface VaultService { @Suspendable fun generateSpend(tx: TransactionBuilder, amount: Amount, - to: PublicKey, + to: AbstractParty, onlyFromParties: Set? = null): Pair> // DOCSTART VaultStatesQuery diff --git a/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt b/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt index fccf706b97..36293c7773 100644 --- a/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt @@ -7,6 +7,7 @@ import net.corda.core.contracts.StateRef import net.corda.core.crypto.* import net.corda.core.flows.FlowException import net.corda.core.flows.FlowLogic +import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.transactions.SignedTransaction @@ -59,13 +60,13 @@ abstract class AbstractStateReplacementFlow { progressTracker.currentStep = SIGNING - val myKey = serviceHub.myInfo.legalIdentity.owningKey + val myKey = serviceHub.myInfo.legalIdentity val me = listOf(myKey) val signatures = if (participants == me) { getNotarySignatures(stx) } else { - collectSignatures(participants - me, stx) + collectSignatures((participants - me).map { it.owningKey }, stx) } val finalTx = stx + signatures @@ -73,7 +74,7 @@ abstract class AbstractStateReplacementFlow { return finalTx.tx.outRef(0) } - abstract protected fun assembleTx(): Pair> + abstract protected fun assembleTx(): Pair> @Suspendable private fun collectSignatures(participants: Iterable, stx: SignedTransaction): List { diff --git a/core/src/main/kotlin/net/corda/flows/ContractUpgradeFlow.kt b/core/src/main/kotlin/net/corda/flows/ContractUpgradeFlow.kt index 8c1cb1e437..3a26e3ef29 100644 --- a/core/src/main/kotlin/net/corda/flows/ContractUpgradeFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/ContractUpgradeFlow.kt @@ -3,6 +3,7 @@ package net.corda.flows import net.corda.core.contracts.* import net.corda.core.flows.InitiatingFlow import net.corda.core.flows.StartableByRPC +import net.corda.core.identity.AbstractParty import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder import java.security.PublicKey @@ -32,12 +33,12 @@ class ContractUpgradeFlow = input.participants.toSet() + val participantKeys: Set = input.participants.map { it.owningKey }.toSet() val keysThatSigned: Set = commandData.signers.toSet() @Suppress("UNCHECKED_CAST") val upgradedContract = command.upgradedContractClass.newInstance() as UpgradedContract requireThat { - "The signing keys include all participant keys" using keysThatSigned.containsAll(participants) + "The signing keys include all participant keys" using keysThatSigned.containsAll(participantKeys) "Inputs state reference the legacy contract" using (input.contract.javaClass == upgradedContract.legacyContract) "Outputs state reference the upgraded contract" using (output.contract.javaClass == command.upgradedContractClass) "Output state must be an upgraded version of the input state" using (output == upgradedContract.upgrade(input)) @@ -53,11 +54,11 @@ class ContractUpgradeFlow> { + override fun assembleTx(): Pair> { val stx = assembleBareTx(originalState, modification) .signWith(serviceHub.legalIdentityKey) .toSignedTransaction(false) diff --git a/core/src/main/kotlin/net/corda/flows/FinalityFlow.kt b/core/src/main/kotlin/net/corda/flows/FinalityFlow.kt index 4949c08a5a..bcd56e5f85 100644 --- a/core/src/main/kotlin/net/corda/flows/FinalityFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/FinalityFlow.kt @@ -105,7 +105,7 @@ class FinalityFlow(val transactions: Iterable, // Calculate who is meant to see the results based on the participants involved. val keys = ltx.outputs.flatMap { it.data.participants } + ltx.inputs.flatMap { it.state.data.participants } // TODO: Is it safe to drop participants we don't know how to contact? Does not knowing how to contact them count as a reason to fail? - val parties = keys.mapNotNull { serviceHub.identityService.partyFromKey(it) }.toSet() + val parties = keys.mapNotNull { serviceHub.identityService.partyFromAnonymous(it) }.toSet() Pair(stx, parties) } } diff --git a/core/src/main/kotlin/net/corda/flows/NotaryChangeFlow.kt b/core/src/main/kotlin/net/corda/flows/NotaryChangeFlow.kt index 4a80599021..d820d14c2d 100644 --- a/core/src/main/kotlin/net/corda/flows/NotaryChangeFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/NotaryChangeFlow.kt @@ -2,6 +2,7 @@ package net.corda.flows import net.corda.core.contracts.* import net.corda.core.flows.InitiatingFlow +import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder @@ -24,11 +25,11 @@ class NotaryChangeFlow( progressTracker: ProgressTracker = tracker()) : AbstractStateReplacementFlow.Instigator(originalState, newNotary, progressTracker) { - override fun assembleTx(): Pair> { + override fun assembleTx(): Pair> { val state = originalState.state val tx = TransactionType.NotaryChange.Builder(originalState.state.notary) - val participants: Iterable + val participants: Iterable if (state.encumbrance == null) { val modifiedState = TransactionState(state.data, modification) @@ -53,14 +54,14 @@ class NotaryChangeFlow( * * @return union of all added states' participants */ - private fun resolveEncumbrances(tx: TransactionBuilder): Iterable { + private fun resolveEncumbrances(tx: TransactionBuilder): Iterable { val stateRef = originalState.ref val txId = stateRef.txhash val issuingTx = serviceHub.storageService.validatedTransactions.getTransaction(txId) ?: throw StateReplacementException("Transaction $txId not found") val outputs = issuingTx.tx.outputs - val participants = mutableSetOf() + val participants = mutableSetOf() var nextStateIndex = stateRef.index var newOutputPosition = tx.outputStates().size diff --git a/core/src/main/resources/net/corda/core/node/isolated.jar b/core/src/main/resources/net/corda/core/node/isolated.jar index 1d6808b4b0..e2db13bf3c 100644 Binary files a/core/src/main/resources/net/corda/core/node/isolated.jar and b/core/src/main/resources/net/corda/core/node/isolated.jar differ diff --git a/core/src/test/kotlin/net/corda/core/contracts/DummyContractV2Tests.kt b/core/src/test/kotlin/net/corda/core/contracts/DummyContractV2Tests.kt index 1e5034b681..dfe175ded2 100644 --- a/core/src/test/kotlin/net/corda/core/contracts/DummyContractV2Tests.kt +++ b/core/src/test/kotlin/net/corda/core/contracts/DummyContractV2Tests.kt @@ -1,6 +1,7 @@ package net.corda.core.contracts import net.corda.core.crypto.SecureHash +import net.corda.core.utilities.ALICE import net.corda.core.utilities.DUMMY_NOTARY import net.corda.testing.ALICE_PUBKEY import org.junit.Test @@ -14,7 +15,7 @@ class DummyContractV2Tests { @Test fun `upgrade from v1`() { val contractUpgrade = DummyContractV2() - val v1State = TransactionState(DummyContract.SingleOwnerState(0, ALICE_PUBKEY), DUMMY_NOTARY) + val v1State = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DUMMY_NOTARY) val v1Ref = StateRef(SecureHash.randomSHA256(), 0) val v1StateAndRef = StateAndRef(v1State, v1Ref) val (tx, _) = DummyContractV2().generateUpgradeFromV1(v1StateAndRef) diff --git a/core/src/test/kotlin/net/corda/core/contracts/TransactionEncumbranceTests.kt b/core/src/test/kotlin/net/corda/core/contracts/TransactionEncumbranceTests.kt index a00380e7df..8fd3bad22a 100644 --- a/core/src/test/kotlin/net/corda/core/contracts/TransactionEncumbranceTests.kt +++ b/core/src/test/kotlin/net/corda/core/contracts/TransactionEncumbranceTests.kt @@ -2,13 +2,12 @@ package net.corda.core.contracts import net.corda.contracts.asset.Cash import net.corda.core.crypto.SecureHash -import net.corda.core.utilities.DUMMY_PUBKEY_1 -import net.corda.core.utilities.DUMMY_PUBKEY_2 +import net.corda.core.identity.AbstractParty import net.corda.testing.MEGA_CORP +import net.corda.testing.MINI_CORP import net.corda.testing.ledger import net.corda.testing.transaction import org.junit.Test -import java.security.PublicKey import java.time.Instant import java.time.temporal.ChronoUnit @@ -19,9 +18,9 @@ class TransactionEncumbranceTests { val state = Cash.State( amount = 1000.DOLLARS `issued by` defaultIssuer, - owner = DUMMY_PUBKEY_1 + owner = MEGA_CORP ) - val stateWithNewOwner = state.copy(owner = DUMMY_PUBKEY_2) + val stateWithNewOwner = state.copy(owner = MINI_CORP) val FOUR_PM: Instant = Instant.parse("2015-04-17T16:00:00.00Z") val FIVE_PM: Instant = FOUR_PM.plus(1, ChronoUnit.HOURS) @@ -40,7 +39,7 @@ class TransactionEncumbranceTests { data class State( val validFrom: Instant ) : ContractState { - override val participants: List = emptyList() + override val participants: List = emptyList() override val contract: Contract = TEST_TIMELOCK_ID } } @@ -52,7 +51,7 @@ class TransactionEncumbranceTests { input { state } output(encumbrance = 1) { stateWithNewOwner } output("5pm time-lock") { timeLock } - command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + command(MEGA_CORP.owningKey) { Cash.Commands.Move() } verifies() } } @@ -70,7 +69,7 @@ class TransactionEncumbranceTests { input("state encumbered by 5pm time-lock") input("5pm time-lock") output { stateWithNewOwner } - command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + command(MEGA_CORP.owningKey) { Cash.Commands.Move() } timestamp(FIVE_PM) verifies() } @@ -89,7 +88,7 @@ class TransactionEncumbranceTests { input("state encumbered by 5pm time-lock") input("5pm time-lock") output { state } - command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + command(MEGA_CORP.owningKey) { Cash.Commands.Move() } timestamp(FOUR_PM) this `fails with` "the time specified in the time-lock has passed" } @@ -106,7 +105,7 @@ class TransactionEncumbranceTests { transaction { input("state encumbered by 5pm time-lock") output { stateWithNewOwner } - command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + command(MEGA_CORP.owningKey) { Cash.Commands.Move() } timestamp(FIVE_PM) this `fails with` "Missing required encumbrance 1 in INPUT" } @@ -118,7 +117,7 @@ class TransactionEncumbranceTests { transaction { input { state } output(encumbrance = 0) { stateWithNewOwner } - command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + command(MEGA_CORP.owningKey) { Cash.Commands.Move() } this `fails with` "Missing required encumbrance 0 in OUTPUT" } } @@ -129,7 +128,7 @@ class TransactionEncumbranceTests { input { state } output(encumbrance = 2) { stateWithNewOwner } output { timeLock } - command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + command(MEGA_CORP.owningKey) { Cash.Commands.Move() } this `fails with` "Missing required encumbrance 2 in OUTPUT" } } @@ -146,7 +145,7 @@ class TransactionEncumbranceTests { input("state encumbered by some other state") input("5pm time-lock") output { stateWithNewOwner } - command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } + command(MEGA_CORP.owningKey) { Cash.Commands.Move() } timestamp(FIVE_PM) this `fails with` "Missing required encumbrance 1 in INPUT" } diff --git a/core/src/test/kotlin/net/corda/core/contracts/TransactionTests.kt b/core/src/test/kotlin/net/corda/core/contracts/TransactionTests.kt index c4a777948c..05b2e39479 100644 --- a/core/src/test/kotlin/net/corda/core/contracts/TransactionTests.kt +++ b/core/src/test/kotlin/net/corda/core/contracts/TransactionTests.kt @@ -11,7 +11,6 @@ import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.WireTransaction import net.corda.core.utilities.* -import net.corda.testing.ALICE_PUBKEY import org.junit.Test import java.security.KeyPair import kotlin.test.assertEquals @@ -95,7 +94,7 @@ class TransactionTests { @Test fun `transactions with no inputs can have any notary`() { - val baseOutState = TransactionState(DummyContract.SingleOwnerState(0, ALICE_PUBKEY), DUMMY_NOTARY) + val baseOutState = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DUMMY_NOTARY) val inputs = emptyList>() val outputs = listOf(baseOutState, baseOutState.copy(notary = ALICE), baseOutState.copy(notary = BOB)) val commands = emptyList>() @@ -120,7 +119,7 @@ class TransactionTests { @Test fun `transaction verification fails for duplicate inputs`() { - val baseOutState = TransactionState(DummyContract.SingleOwnerState(0, ALICE_PUBKEY), DUMMY_NOTARY) + val baseOutState = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DUMMY_NOTARY) val stateRef = StateRef(SecureHash.randomSHA256(), 0) val stateAndRef = StateAndRef(baseOutState, stateRef) val inputs = listOf(stateAndRef, stateAndRef) @@ -148,7 +147,7 @@ class TransactionTests { @Test fun `general transactions cannot change notary`() { val notary: Party = DUMMY_NOTARY - val inState = TransactionState(DummyContract.SingleOwnerState(0, ALICE_PUBKEY), notary) + val inState = TransactionState(DummyContract.SingleOwnerState(0, ALICE), notary) val outState = inState.copy(notary = ALICE) val inputs = listOf(StateAndRef(inState, StateRef(SecureHash.randomSHA256(), 0))) val outputs = listOf(outState) diff --git a/core/src/test/kotlin/net/corda/core/crypto/PartialMerkleTreeTest.kt b/core/src/test/kotlin/net/corda/core/crypto/PartialMerkleTreeTest.kt index 18d0b5923e..dbbc52c5e0 100644 --- a/core/src/test/kotlin/net/corda/core/crypto/PartialMerkleTreeTest.kt +++ b/core/src/test/kotlin/net/corda/core/crypto/PartialMerkleTreeTest.kt @@ -12,9 +12,7 @@ import net.corda.core.transactions.WireTransaction import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.DUMMY_PUBKEY_1 import net.corda.core.utilities.TEST_TX_TIME -import net.corda.testing.MEGA_CORP -import net.corda.testing.MEGA_CORP_PUBKEY -import net.corda.testing.ledger +import net.corda.testing.* import org.junit.Test import java.security.PublicKey import kotlin.test.* @@ -30,20 +28,20 @@ class PartialMerkleTreeTest { output("MEGA_CORP cash") { Cash.State( amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1), - owner = MEGA_CORP_PUBKEY + owner = MEGA_CORP ) } output("dummy cash 1") { Cash.State( amount = 900.DOLLARS `issued by` MEGA_CORP.ref(1, 1), - owner = DUMMY_PUBKEY_1 + owner = MINI_CORP ) } } transaction { input("MEGA_CORP cash") - output("MEGA_CORP cash".output().copy(owner = DUMMY_PUBKEY_1)) + output("MEGA_CORP cash".output().copy(owner = MINI_CORP)) command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() } timestamp(TEST_TX_TIME) this.verifies() @@ -98,7 +96,7 @@ class PartialMerkleTreeTest { fun filtering(elem: Any): Boolean { return when (elem) { is StateRef -> true - is TransactionState<*> -> elem.data.participants[0].keys == DUMMY_PUBKEY_1.keys + is TransactionState<*> -> elem.data.participants[0].owningKey.keys == MINI_CORP_PUBKEY.keys is Command -> MEGA_CORP_PUBKEY in elem.signers is Timestamp -> true is PublicKey -> elem == MEGA_CORP_PUBKEY diff --git a/core/src/test/kotlin/net/corda/core/flows/CollectSignaturesFlowTests.kt b/core/src/test/kotlin/net/corda/core/flows/CollectSignaturesFlowTests.kt index cbfdd7cba0..080a9d19a4 100644 --- a/core/src/test/kotlin/net/corda/core/flows/CollectSignaturesFlowTests.kt +++ b/core/src/test/kotlin/net/corda/core/flows/CollectSignaturesFlowTests.kt @@ -88,7 +88,7 @@ class CollectSignaturesFlowTests { val state = receive(otherParty).unwrap { it } val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity - val command = Command(DummyContract.Commands.Create(), state.participants) + val command = Command(DummyContract.Commands.Create(), state.participants.map { it.owningKey }) val builder = TransactionType.General.Builder(notary = notary).withItems(state, command) val ptx = builder.signWith(serviceHub.legalIdentityKey).toSignedTransaction(false) val stx = subFlow(CollectSignaturesFlow(ptx)) @@ -108,7 +108,7 @@ class CollectSignaturesFlowTests { @Suspendable override fun call(): SignedTransaction { val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity - val command = Command(DummyContract.Commands.Create(), state.participants) + val command = Command(DummyContract.Commands.Create(), state.participants.map { it.owningKey }) val builder = TransactionType.General.Builder(notary = notary).withItems(state, command) val ptx = builder.signWith(serviceHub.legalIdentityKey).toSignedTransaction(false) val stx = subFlow(CollectSignaturesFlow(ptx)) @@ -142,7 +142,7 @@ class CollectSignaturesFlowTests { fun `successfully collects two signatures`() { val magicNumber = 1337 val parties = listOf(a.info.legalIdentity, b.info.legalIdentity, c.info.legalIdentity) - val state = DummyContract.MultiOwnerState(magicNumber, parties.map { it.owningKey }) + val state = DummyContract.MultiOwnerState(magicNumber, parties) val flow = a.services.startFlow(TestFlowTwo.Initiator(state, b.info.legalIdentity)) mockNet.runNetwork() val result = flow.resultFuture.getOrThrow() diff --git a/core/src/test/kotlin/net/corda/core/flows/ContractUpgradeFlowTest.kt b/core/src/test/kotlin/net/corda/core/flows/ContractUpgradeFlowTest.kt index bdd09610bd..1fb879e6ec 100644 --- a/core/src/test/kotlin/net/corda/core/flows/ContractUpgradeFlowTest.kt +++ b/core/src/test/kotlin/net/corda/core/flows/ContractUpgradeFlowTest.kt @@ -5,6 +5,7 @@ import net.corda.contracts.asset.Cash import net.corda.core.contracts.* import net.corda.core.crypto.SecureHash import net.corda.core.getOrThrow +import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.startFlow @@ -27,7 +28,6 @@ import net.corda.testing.startRpcClient import org.junit.After import org.junit.Before import org.junit.Test -import java.security.PublicKey import java.util.* import kotlin.test.assertEquals import kotlin.test.assertFailsWith @@ -187,21 +187,21 @@ class ContractUpgradeFlowTest { val firstState = a.database.transaction { a.vault.unconsumedStates().single() } assertTrue(firstState.state.data is CashV2.State, "Contract state is upgraded to the new version.") assertEquals(Amount(1000000, USD).`issued by`(a.info.legalIdentity.ref(1)), (firstState.state.data as CashV2.State).amount, "Upgraded cash contain the correct amount.") - assertEquals(listOf(a.info.legalIdentity.owningKey), (firstState.state.data as CashV2.State).owners, "Upgraded cash belongs to the right owner.") + assertEquals>(listOf(a.info.legalIdentity), (firstState.state.data as CashV2.State).owners, "Upgraded cash belongs to the right owner.") } class CashV2 : UpgradedContract { override val legacyContract = Cash::class.java - data class State(override val amount: Amount>, val owners: List) : FungibleAsset { - override val owner: PublicKey = owners.first() - override val exitKeys = (owners + amount.token.issuer.party.owningKey).toSet() + data class State(override val amount: Amount>, val owners: List) : FungibleAsset { + override val owner: AbstractParty = owners.first() + override val exitKeys = (owners + amount.token.issuer.party).map { it.owningKey }.toSet() override val contract = CashV2() override val participants = owners - override fun move(newAmount: Amount>, newOwner: PublicKey) = copy(amount = amount.copy(newAmount.quantity), owners = listOf(newOwner)) + override fun move(newAmount: Amount>, newOwner: AbstractParty) = copy(amount = amount.copy(newAmount.quantity), owners = listOf(newOwner)) override fun toString() = "${Emoji.bagOfCash}New Cash($amount at ${amount.token.issuer} owned by $owner)" - override fun withNewOwner(newOwner: PublicKey) = Pair(Cash.Commands.Move(), copy(owners = listOf(newOwner))) + override fun withNewOwner(newOwner: AbstractParty) = Pair(Cash.Commands.Move(), copy(owners = listOf(newOwner))) } override fun upgrade(state: Cash.State) = CashV2.State(state.amount.times(1000), listOf(state.owner)) diff --git a/core/src/test/kotlin/net/corda/core/flows/ResolveTransactionsFlowTest.kt b/core/src/test/kotlin/net/corda/core/flows/ResolveTransactionsFlowTest.kt index 71eb351cbc..a48e72944f 100644 --- a/core/src/test/kotlin/net/corda/core/flows/ResolveTransactionsFlowTest.kt +++ b/core/src/test/kotlin/net/corda/core/flows/ResolveTransactionsFlowTest.kt @@ -12,7 +12,7 @@ import net.corda.flows.ResolveTransactionsFlow import net.corda.node.utilities.transaction import net.corda.testing.MEGA_CORP import net.corda.testing.MEGA_CORP_KEY -import net.corda.testing.MINI_CORP_PUBKEY +import net.corda.testing.MINI_CORP import net.corda.testing.node.MockNetwork import org.junit.After import org.junit.Before @@ -94,7 +94,7 @@ class ResolveTransactionsFlowTest { val count = 50 var cursor = stx2 repeat(count) { - val stx = DummyContract.move(cursor.tx.outRef(0), MINI_CORP_PUBKEY) + val stx = DummyContract.move(cursor.tx.outRef(0), MINI_CORP) .addSignatureUnchecked(NullSignature) .toSignedTransaction(false) a.database.transaction { @@ -113,13 +113,13 @@ class ResolveTransactionsFlowTest { fun `triangle of transactions resolves fine`() { val stx1 = makeTransactions().first - val stx2 = DummyContract.move(stx1.tx.outRef(0), MINI_CORP_PUBKEY).run { + val stx2 = DummyContract.move(stx1.tx.outRef(0), MINI_CORP).run { signWith(MEGA_CORP_KEY) signWith(DUMMY_NOTARY_KEY) toSignedTransaction() } - val stx3 = DummyContract.move(listOf(stx1.tx.outRef(0), stx2.tx.outRef(0)), MINI_CORP_PUBKEY).run { + val stx3 = DummyContract.move(listOf(stx1.tx.outRef(0), stx2.tx.outRef(0)), MINI_CORP).run { signWith(MEGA_CORP_KEY) signWith(DUMMY_NOTARY_KEY) toSignedTransaction() @@ -173,7 +173,7 @@ class ResolveTransactionsFlowTest { it.signWith(DUMMY_NOTARY_KEY) it.toSignedTransaction(false) } - val dummy2: SignedTransaction = DummyContract.move(dummy1.tx.outRef(0), MINI_CORP_PUBKEY).let { + val dummy2: SignedTransaction = DummyContract.move(dummy1.tx.outRef(0), MINI_CORP).let { it.signWith(MEGA_CORP_KEY) it.signWith(DUMMY_NOTARY_KEY) it.toSignedTransaction() diff --git a/core/src/test/kotlin/net/corda/core/node/AttachmentClassLoaderTests.kt b/core/src/test/kotlin/net/corda/core/node/AttachmentClassLoaderTests.kt index 33db2d08e2..127103ae5f 100644 --- a/core/src/test/kotlin/net/corda/core/node/AttachmentClassLoaderTests.kt +++ b/core/src/test/kotlin/net/corda/core/node/AttachmentClassLoaderTests.kt @@ -5,6 +5,7 @@ import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.whenever import net.corda.core.contracts.* import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.node.services.AttachmentStorage import net.corda.core.node.services.StorageService @@ -53,7 +54,7 @@ class AttachmentClassLoaderTests { class AttachmentDummyContract : Contract { data class State(val magicNumber: Int = 0) : ContractState { override val contract = ATTACHMENT_TEST_PROGRAM_ID - override val participants: List + override val participants: List get() = listOf() } diff --git a/core/src/test/kotlin/net/corda/core/node/VaultUpdateTests.kt b/core/src/test/kotlin/net/corda/core/node/VaultUpdateTests.kt index a5e5dbd951..9b15ca200e 100644 --- a/core/src/test/kotlin/net/corda/core/node/VaultUpdateTests.kt +++ b/core/src/test/kotlin/net/corda/core/node/VaultUpdateTests.kt @@ -2,10 +2,10 @@ package net.corda.core.node import net.corda.core.contracts.* import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty import net.corda.core.node.services.Vault import net.corda.core.utilities.DUMMY_NOTARY import org.junit.Test -import java.security.PublicKey import kotlin.test.assertEquals @@ -20,7 +20,7 @@ class VaultUpdateTests { } private class DummyState : ContractState { - override val participants: List + override val participants: List get() = emptyList() override val contract = VaultUpdateTests.DummyContract } diff --git a/core/src/test/kotlin/net/corda/core/serialization/TransactionSerializationTests.kt b/core/src/test/kotlin/net/corda/core/serialization/TransactionSerializationTests.kt index 8108ac17f3..e0e1cd17df 100644 --- a/core/src/test/kotlin/net/corda/core/serialization/TransactionSerializationTests.kt +++ b/core/src/test/kotlin/net/corda/core/serialization/TransactionSerializationTests.kt @@ -2,14 +2,19 @@ package net.corda.core.serialization import net.corda.core.contracts.* import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty import net.corda.core.seconds import net.corda.core.transactions.TransactionBuilder -import net.corda.core.utilities.* +import net.corda.core.utilities.DUMMY_KEY_2 +import net.corda.core.utilities.DUMMY_NOTARY +import net.corda.core.utilities.DUMMY_NOTARY_KEY +import net.corda.core.utilities.TEST_TX_TIME +import net.corda.testing.MEGA_CORP +import net.corda.testing.MEGA_CORP_KEY import net.corda.testing.MINI_CORP import net.corda.testing.generateStateRef import org.junit.Before import org.junit.Test -import java.security.PublicKey import java.security.SignatureException import java.util.* import kotlin.test.assertEquals @@ -27,12 +32,12 @@ class TransactionSerializationTests { data class State( val deposit: PartyAndReference, val amount: Amount, - override val owner: PublicKey) : OwnableState { + override val owner: AbstractParty) : OwnableState { override val contract: Contract = TEST_PROGRAM_ID - override val participants: List + override val participants: List get() = listOf(owner) - override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner)) + override fun withNewOwner(newOwner: AbstractParty) = Pair(Commands.Move(), copy(owner = newOwner)) } interface Commands : CommandData { @@ -44,9 +49,9 @@ class TransactionSerializationTests { // It refers to a fake TX/state that we don't bother creating here. val depositRef = MINI_CORP.ref(1) val fakeStateRef = generateStateRef() - val inputState = StateAndRef(TransactionState(TestCash.State(depositRef, 100.POUNDS, DUMMY_PUBKEY_1), DUMMY_NOTARY), fakeStateRef) - val outputState = TransactionState(TestCash.State(depositRef, 600.POUNDS, DUMMY_PUBKEY_1), DUMMY_NOTARY) - val changeState = TransactionState(TestCash.State(depositRef, 400.POUNDS, DUMMY_KEY_1.public), DUMMY_NOTARY) + val inputState = StateAndRef(TransactionState(TestCash.State(depositRef, 100.POUNDS, MEGA_CORP), DUMMY_NOTARY), fakeStateRef) + val outputState = TransactionState(TestCash.State(depositRef, 600.POUNDS, MEGA_CORP), DUMMY_NOTARY) + val changeState = TransactionState(TestCash.State(depositRef, 400.POUNDS, MEGA_CORP), DUMMY_NOTARY) lateinit var tx: TransactionBuilder @@ -54,14 +59,14 @@ class TransactionSerializationTests { @Before fun setup() { tx = TransactionType.General.Builder(DUMMY_NOTARY).withItems( - inputState, outputState, changeState, Command(TestCash.Commands.Move(), arrayListOf(DUMMY_KEY_1.public)) + inputState, outputState, changeState, Command(TestCash.Commands.Move(), arrayListOf(MEGA_CORP.owningKey)) ) } @Test fun signWireTX() { tx.signWith(DUMMY_NOTARY_KEY) - tx.signWith(DUMMY_KEY_1) + tx.signWith(MEGA_CORP_KEY) val signedTX = tx.toSignedTransaction() // Now check that the signature we just made verifies. @@ -81,7 +86,7 @@ class TransactionSerializationTests { tx.toSignedTransaction() } - tx.signWith(DUMMY_KEY_1) + tx.signWith(MEGA_CORP_KEY) tx.signWith(DUMMY_NOTARY_KEY) val signedTX = tx.toSignedTransaction() @@ -104,7 +109,7 @@ class TransactionSerializationTests { @Test fun timestamp() { tx.setTime(TEST_TX_TIME, 30.seconds) - tx.signWith(DUMMY_KEY_1) + tx.signWith(MEGA_CORP_KEY) tx.signWith(DUMMY_NOTARY_KEY) val stx = tx.toSignedTransaction() assertEquals(TEST_TX_TIME, stx.tx.timestamp?.midpoint) diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 785de5b597..ca79057a52 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -38,10 +38,9 @@ UNRELEASED * ``Party`` has moved to the ``net.corda.core.identity`` package; there is a deprecated class in its place for backwards compatibility, but it will be removed in a future release and developers should move to the new class as soon as possible. - * There is a new ``AbstractParty`` superclass to ``Party``, which contains just the public key. A new class - ``AnonymousParty`` has been added, which is intended to be used in place of ``Party`` or ``PublicKey`` in contract - state objects. The exception to this is where the party in a contract state is intended to be well known, such as - issuer of a ``Cash`` state. + * There is a new ``AbstractParty`` superclass to ``Party``, which contains just the public key. This now replaces + use of ``Party`` and ``PublicKey`` in state objects, and allows use of full or anonymised parties depending on + use-case. * Names of parties are now stored as a ``X500Name`` rather than a ``String``, to correctly enforce basic structure of the name. As a result all node legal names must now be structured as X.500 distinguished names. diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt index e33319c094..f70c196073 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt @@ -48,12 +48,12 @@ private fun gatherOurInputs(serviceHub: ServiceHub, notary: Party?): Pair>, Long> { // Collect cash type inputs val cashStates = serviceHub.vaultService.unconsumedStates() - // extract our key identity for convenience - val ourKey = serviceHub.myInfo.legalIdentity.owningKey + // extract our identity for convenience + val ourIdentity = serviceHub.myInfo.legalIdentity // Filter down to our own cash states with right currency and issuer val suitableCashStates = cashStates.filter { val state = it.state.data - (state.owner == ourKey) + (state.owner == ourIdentity) && (state.amount.token == amountRequired.token) } require(!suitableCashStates.isEmpty()) { "Insufficient funds" } @@ -90,12 +90,12 @@ private fun prepareOurInputsAndOutputs(serviceHub: ServiceHub, request: FxReques val (inputs, residual) = gatherOurInputs(serviceHub, sellAmount, request.notary) // Build and an output state for the counterparty - val transferedFundsOutput = Cash.State(sellAmount, request.counterparty.owningKey) + val transferedFundsOutput = Cash.State(sellAmount, request.counterparty) if (residual > 0L) { // Build an output state for the residual change back to us val residualAmount = Amount(residual, sellAmount.token) - val residualOutput = Cash.State(residualAmount, serviceHub.myInfo.legalIdentity.owningKey) + val residualOutput = Cash.State(residualAmount, serviceHub.myInfo.legalIdentity) return FxResponse(inputs, listOf(transferedFundsOutput, residualOutput)) } else { return FxResponse(inputs, listOf(transferedFundsOutput)) @@ -140,7 +140,7 @@ class ForeignExchangeFlow(val tradeId: String, require(it.inputs.all { it.state.notary == notary }) { "notary of remote states must be same as for our states" } - require(it.inputs.all { it.state.data.owner == remoteRequestWithNotary.owner.owningKey }) { + require(it.inputs.all { it.state.data.owner == remoteRequestWithNotary.owner }) { "The inputs are not owned by the correct counterparty" } require(it.inputs.all { it.state.data.amount.token == remoteRequestWithNotary.amount.token }) { @@ -153,7 +153,7 @@ class ForeignExchangeFlow(val tradeId: String, >= remoteRequestWithNotary.amount.quantity) { "the provided inputs don't provide sufficient funds" } - require(it.outputs.filter { it.owner == serviceHub.myInfo.legalIdentity.owningKey }. + require(it.outputs.filter { it.owner == serviceHub.myInfo.legalIdentity }. map { it.amount.quantity }.sum() == remoteRequestWithNotary.amount.quantity) { "the provided outputs don't provide the request quantity" } @@ -195,8 +195,8 @@ class ForeignExchangeFlow(val tradeId: String, val builder = TransactionType.General.Builder(ourStates.inputs.first().state.notary) // Add the move commands and key to indicate all the respective owners and need to sign - val ourSigners = ourStates.inputs.map { it.state.data.owner }.toSet() - val theirSigners = theirStates.inputs.map { it.state.data.owner }.toSet() + val ourSigners = ourStates.inputs.map { it.state.data.owner.owningKey }.toSet() + val theirSigners = theirStates.inputs.map { it.state.data.owner.owningKey }.toSet() builder.addCommand(Cash.Commands.Move(), (ourSigners + theirSigners).toList()) // Build and add the inputs and outputs diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt index ccb6829894..5a9a3016d9 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt @@ -2,9 +2,13 @@ package net.corda.docs import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.* -import net.corda.core.crypto.* +import net.corda.core.crypto.DigitalSignature +import net.corda.core.crypto.SecureHash +import net.corda.core.crypto.containsAny +import net.corda.core.crypto.sign import net.corda.core.flows.FlowLogic import net.corda.core.flows.InitiatingFlow +import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.node.PluginServiceHub import net.corda.core.node.ServiceHub @@ -64,10 +68,10 @@ data class TradeApprovalContract(override val legalContractReference: SecureHash override val contract: TradeApprovalContract = TradeApprovalContract()) : LinearState { val parties: List get() = listOf(source, counterparty) - override val participants: List get() = parties.map { it.owningKey } + override val participants: List get() = parties override fun isRelevant(ourKeys: Set): Boolean { - return participants.any { it.containsAny(ourKeys) } + return participants.any { it.owningKey.containsAny(ourKeys) } } } diff --git a/docs/source/release-notes.rst b/docs/source/release-notes.rst index 47427afd40..02a2ab14cf 100644 --- a/docs/source/release-notes.rst +++ b/docs/source/release-notes.rst @@ -10,7 +10,8 @@ We've added the ability for flows to be versioned by their CorDapp developers. T version of a flow and allows it to reject flow communication with a node which isn't using the same fact. In a future release we allow a node to have multiple versions of the same flow running to enable backwards compatibility. -There are major changes to the ``Party`` class as part of confidential identities. See :doc:`changelog` for full details. +There are major changes to the ``Party`` class as part of confidential identities, and how parties and keys are stored +in transaction state objects. See :doc:`changelog` for full details. Milestone 11 diff --git a/experimental/src/main/kotlin/net/corda/contracts/universal/UniversalContract.kt b/experimental/src/main/kotlin/net/corda/contracts/universal/UniversalContract.kt index 24f05f7ff3..f86753bfba 100644 --- a/experimental/src/main/kotlin/net/corda/contracts/universal/UniversalContract.kt +++ b/experimental/src/main/kotlin/net/corda/contracts/universal/UniversalContract.kt @@ -2,16 +2,16 @@ package net.corda.contracts.universal import net.corda.core.contracts.* import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.transactions.TransactionBuilder import java.math.BigDecimal -import java.security.PublicKey import java.time.Instant val UNIVERSAL_PROGRAM_ID = UniversalContract() class UniversalContract : Contract { - data class State(override val participants: List, + data class State(override val participants: List, val details: Arrangement) : ContractState { override val contract = UNIVERSAL_PROGRAM_ID } @@ -316,7 +316,7 @@ class UniversalContract : Contract { override val legalContractReference: SecureHash get() = throw UnsupportedOperationException() - fun generateIssue(tx: TransactionBuilder, arrangement: Arrangement, at: PartyAndReference, notary: PublicKey) { + fun generateIssue(tx: TransactionBuilder, arrangement: Arrangement, at: PartyAndReference, notary: Party) { check(tx.inputStates().isEmpty()) tx.addOutputState(State(listOf(notary), arrangement)) tx.addCommand(Commands.Issue(), at.party.owningKey) diff --git a/experimental/src/test/kotlin/net/corda/contracts/universal/Cap.kt b/experimental/src/test/kotlin/net/corda/contracts/universal/Cap.kt index cbb2a488fd..5d275c2876 100644 --- a/experimental/src/test/kotlin/net/corda/contracts/universal/Cap.kt +++ b/experimental/src/test/kotlin/net/corda/contracts/universal/Cap.kt @@ -130,15 +130,15 @@ class Cap { val paymentFinal = arrange { highStreetBank.owes(acmeCorp, 250.K, EUR) } - val stateInitial = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractInitial) + val stateInitial = UniversalContract.State(listOf(DUMMY_NOTARY), contractInitial) - val stateAfterFixingFirst = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractAfterFixingFirst) + val stateAfterFixingFirst = UniversalContract.State(listOf(DUMMY_NOTARY), contractAfterFixingFirst) - val stateAfterExecutionFirst = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractAfterExecutionFirst) - val statePaymentFirst = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), paymentFirst) + val stateAfterExecutionFirst = UniversalContract.State(listOf(DUMMY_NOTARY), contractAfterExecutionFirst) + val statePaymentFirst = UniversalContract.State(listOf(DUMMY_NOTARY), paymentFirst) - val stateAfterFixingFinal = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractAfterFixingFinal) - val statePaymentFinal = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), paymentFinal) + val stateAfterFixingFinal = UniversalContract.State(listOf(DUMMY_NOTARY), contractAfterFixingFinal) + val statePaymentFinal = UniversalContract.State(listOf(DUMMY_NOTARY), paymentFinal) val contractLimitedCap = arrange { rollOut("2016-04-01".ld, "2017-04-01".ld, Frequency.SemiAnnual, object { diff --git a/experimental/src/test/kotlin/net/corda/contracts/universal/Caplet.kt b/experimental/src/test/kotlin/net/corda/contracts/universal/Caplet.kt index 634d1964a6..0c69005b22 100644 --- a/experimental/src/test/kotlin/net/corda/contracts/universal/Caplet.kt +++ b/experimental/src/test/kotlin/net/corda/contracts/universal/Caplet.kt @@ -44,11 +44,11 @@ class Caplet { val contractFinal = arrange { highStreetBank.owes(acmeCorp, 250.K, EUR) } - val stateStart = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contract) + val stateStart = UniversalContract.State(listOf(DUMMY_NOTARY), contract) - val stateFixed = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractFixed) + val stateFixed = UniversalContract.State(listOf(DUMMY_NOTARY), contractFixed) - val stateFinal = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractFinal) + val stateFinal = UniversalContract.State(listOf(DUMMY_NOTARY), contractFinal) @Test fun issue() { diff --git a/experimental/src/test/kotlin/net/corda/contracts/universal/FXFwdTimeOption.kt b/experimental/src/test/kotlin/net/corda/contracts/universal/FXFwdTimeOption.kt index 4265468ac2..9bea6c3c37 100644 --- a/experimental/src/test/kotlin/net/corda/contracts/universal/FXFwdTimeOption.kt +++ b/experimental/src/test/kotlin/net/corda/contracts/universal/FXFwdTimeOption.kt @@ -43,9 +43,9 @@ class FXFwdTimeOption val TEST_TX_TIME_BEFORE_MATURITY: Instant get() = Instant.parse("2018-05-01T12:00:00.00Z") val TEST_TX_TIME_AFTER_MATURITY: Instant get() = Instant.parse("2018-06-02T12:00:00.00Z") - val inState = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), initialContract) - val outState1 = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), outContract1) - val outState2 = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), outContract2) + val inState = UniversalContract.State(listOf(DUMMY_NOTARY), initialContract) + val outState1 = UniversalContract.State(listOf(DUMMY_NOTARY), outContract1) + val outState2 = UniversalContract.State(listOf(DUMMY_NOTARY), outContract2) @Test fun `issue - signature`() { diff --git a/experimental/src/test/kotlin/net/corda/contracts/universal/FXSwap.kt b/experimental/src/test/kotlin/net/corda/contracts/universal/FXSwap.kt index 38495f2e06..272ae30171 100644 --- a/experimental/src/test/kotlin/net/corda/contracts/universal/FXSwap.kt +++ b/experimental/src/test/kotlin/net/corda/contracts/universal/FXSwap.kt @@ -25,18 +25,18 @@ class FXSwap { val transfer1 = arrange { highStreetBank.owes(acmeCorp, 1070.K, EUR) } val transfer2 = arrange { acmeCorp.owes(highStreetBank, 1.M, USD) } - val outState1 = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), transfer1) - val outState2 = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), transfer2) + val outState1 = UniversalContract.State(listOf(DUMMY_NOTARY), transfer1) + val outState2 = UniversalContract.State(listOf(DUMMY_NOTARY), transfer2) val transferBad1 = arrange { highStreetBank.owes(acmeCorp, 1070.K, USD) } // wrong currency val transferBad2 = arrange { acmeCorp.owes(highStreetBank, 900.K, USD) } // wrong amount val transferBad3 = arrange { highStreetBank.owes(highStreetBank, 1070.K, EUR) } // wrong party - val outStateBad1 = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), transferBad1) - val outStateBad2 = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), transferBad2) - val outStateBad3 = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), transferBad3) + val outStateBad1 = UniversalContract.State(listOf(DUMMY_NOTARY), transferBad1) + val outStateBad2 = UniversalContract.State(listOf(DUMMY_NOTARY), transferBad2) + val outStateBad3 = UniversalContract.State(listOf(DUMMY_NOTARY), transferBad3) - val inState = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contract) + val inState = UniversalContract.State(listOf(DUMMY_NOTARY), contract) @Test fun `issue - signature`() { diff --git a/experimental/src/test/kotlin/net/corda/contracts/universal/IRS.kt b/experimental/src/test/kotlin/net/corda/contracts/universal/IRS.kt index 252f70ca70..e80cffc391 100644 --- a/experimental/src/test/kotlin/net/corda/contracts/universal/IRS.kt +++ b/experimental/src/test/kotlin/net/corda/contracts/universal/IRS.kt @@ -122,12 +122,12 @@ class IRS { val paymentFirst = arrange { highStreetBank.owes(acmeCorp, 250.K, EUR) } - val stateInitial = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractInitial) + val stateInitial = UniversalContract.State(listOf(DUMMY_NOTARY), contractInitial) - val stateAfterFixingFirst = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractAfterFixingFirst) - val stateAfterExecutionFirst = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractAfterExecutionFirst) + val stateAfterFixingFirst = UniversalContract.State(listOf(DUMMY_NOTARY), contractAfterFixingFirst) + val stateAfterExecutionFirst = UniversalContract.State(listOf(DUMMY_NOTARY), contractAfterExecutionFirst) - val statePaymentFirst = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), paymentFirst) + val statePaymentFirst = UniversalContract.State(listOf(DUMMY_NOTARY), paymentFirst) @Test diff --git a/experimental/src/test/kotlin/net/corda/contracts/universal/RollOutTests.kt b/experimental/src/test/kotlin/net/corda/contracts/universal/RollOutTests.kt index 13d09b9f7a..c91a78be11 100644 --- a/experimental/src/test/kotlin/net/corda/contracts/universal/RollOutTests.kt +++ b/experimental/src/test/kotlin/net/corda/contracts/universal/RollOutTests.kt @@ -36,7 +36,7 @@ class RollOutTests { } } } - val stateStart = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contract) + val stateStart = UniversalContract.State(listOf(DUMMY_NOTARY), contract) val contractStep1a = arrange { rollOut("2016-10-03".ld, "2017-09-01".ld, Frequency.Monthly) { @@ -55,8 +55,8 @@ class RollOutTests { highStreetBank.owes(acmeCorp, 10.K, USD) } - val stateStep1a = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractStep1a) - val stateStep1b = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractStep1b) + val stateStep1a = UniversalContract.State(listOf(DUMMY_NOTARY), contractStep1a) + val stateStep1b = UniversalContract.State(listOf(DUMMY_NOTARY), contractStep1b) val contract_transfer1 = arrange { highStreetBank.owes(acmeCorp, 10.K, USD) diff --git a/experimental/src/test/kotlin/net/corda/contracts/universal/Swaption.kt b/experimental/src/test/kotlin/net/corda/contracts/universal/Swaption.kt index e1f04921a4..7dea92bc4f 100644 --- a/experimental/src/test/kotlin/net/corda/contracts/universal/Swaption.kt +++ b/experimental/src/test/kotlin/net/corda/contracts/universal/Swaption.kt @@ -54,7 +54,7 @@ class Swaption { } - val stateInitial = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractInitial) + val stateInitial = UniversalContract.State(listOf(DUMMY_NOTARY), contractInitial) @Test fun issue() { diff --git a/experimental/src/test/kotlin/net/corda/contracts/universal/ZeroCouponBond.kt b/experimental/src/test/kotlin/net/corda/contracts/universal/ZeroCouponBond.kt index 6f45ea0742..458bacb4bb 100644 --- a/experimental/src/test/kotlin/net/corda/contracts/universal/ZeroCouponBond.kt +++ b/experimental/src/test/kotlin/net/corda/contracts/universal/ZeroCouponBond.kt @@ -33,12 +33,12 @@ class ZeroCouponBond { val transfer = arrange { highStreetBank.owes(acmeCorp, 100.K, GBP) } val transferWrong = arrange { highStreetBank.owes(acmeCorp, 80.K, GBP) } - val inState = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contract) + val inState = UniversalContract.State(listOf(DUMMY_NOTARY), contract) - val outState = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), transfer) - val outStateWrong = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), transferWrong) + val outState = UniversalContract.State(listOf(DUMMY_NOTARY), transfer) + val outStateWrong = UniversalContract.State(listOf(DUMMY_NOTARY), transferWrong) - val outStateMove = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractMove) + val outStateMove = UniversalContract.State(listOf(DUMMY_NOTARY), contractMove) @Test fun basic() { diff --git a/finance/isolated/src/main/kotlin/net/corda/contracts/AnotherDummyContract.kt b/finance/isolated/src/main/kotlin/net/corda/contracts/AnotherDummyContract.kt index d61a903a38..ae94bab519 100644 --- a/finance/isolated/src/main/kotlin/net/corda/contracts/AnotherDummyContract.kt +++ b/finance/isolated/src/main/kotlin/net/corda/contracts/AnotherDummyContract.kt @@ -3,6 +3,7 @@ package net.corda.contracts.isolated import net.corda.core.contracts.* import net.corda.core.identity.Party import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty import net.corda.core.transactions.TransactionBuilder import java.security.PublicKey @@ -13,7 +14,7 @@ val ANOTHER_DUMMY_PROGRAM_ID = AnotherDummyContract() class AnotherDummyContract : Contract, net.corda.core.node.DummyContractBackdoor { data class State(val magicNumber: Int = 0) : ContractState { override val contract = ANOTHER_DUMMY_PROGRAM_ID - override val participants: List + override val participants: List get() = emptyList() } diff --git a/finance/src/main/java/net/corda/contracts/ICommercialPaperState.java b/finance/src/main/java/net/corda/contracts/ICommercialPaperState.java index a907811919..0923897593 100644 --- a/finance/src/main/java/net/corda/contracts/ICommercialPaperState.java +++ b/finance/src/main/java/net/corda/contracts/ICommercialPaperState.java @@ -1,6 +1,7 @@ package net.corda.contracts; import net.corda.core.contracts.*; +import net.corda.core.identity.AbstractParty; import java.security.PublicKey; import java.time.*; @@ -12,7 +13,7 @@ import java.util.*; * ultimately either language can be used against a common test framework (and therefore can be used for real). */ public interface ICommercialPaperState extends ContractState { - ICommercialPaperState withOwner(PublicKey newOwner); + ICommercialPaperState withOwner(AbstractParty newOwner); ICommercialPaperState withFaceValue(Amount> newFaceValue); diff --git a/finance/src/main/java/net/corda/contracts/JavaCommercialPaper.java b/finance/src/main/java/net/corda/contracts/JavaCommercialPaper.java index a38251e24d..d2bb7eb3f8 100644 --- a/finance/src/main/java/net/corda/contracts/JavaCommercialPaper.java +++ b/finance/src/main/java/net/corda/contracts/JavaCommercialPaper.java @@ -9,6 +9,9 @@ import net.corda.core.contracts.Contract; import net.corda.core.contracts.TransactionForContract.*; import net.corda.core.contracts.clauses.*; import net.corda.core.crypto.*; +import net.corda.core.identity.AbstractParty; +import net.corda.core.identity.AbstractParty; +import net.corda.core.identity.AnonymousParty; import net.corda.core.identity.Party; import net.corda.core.node.services.*; import net.corda.core.transactions.*; @@ -34,14 +37,14 @@ public class JavaCommercialPaper implements Contract { @SuppressWarnings("unused") public static class State implements OwnableState, ICommercialPaperState { private PartyAndReference issuance; - private PublicKey owner; + private AbstractParty owner; private Amount> faceValue; private Instant maturityDate; public State() { } // For serialization - public State(PartyAndReference issuance, PublicKey owner, Amount> faceValue, + public State(PartyAndReference issuance, AbstractParty owner, Amount> faceValue, Instant maturityDate) { this.issuance = issuance; this.owner = owner; @@ -53,13 +56,13 @@ public class JavaCommercialPaper implements Contract { return new State(this.issuance, this.owner, this.faceValue, this.maturityDate); } - public ICommercialPaperState withOwner(PublicKey newOwner) { + public ICommercialPaperState withOwner(AbstractParty newOwner) { return new State(this.issuance, newOwner, this.faceValue, this.maturityDate); } @NotNull @Override - public Pair withNewOwner(@NotNull PublicKey newOwner) { + public Pair withNewOwner(@NotNull AbstractParty newOwner) { return new Pair<>(new Commands.Move(), new State(this.issuance, newOwner, this.faceValue, this.maturityDate)); } @@ -76,7 +79,7 @@ public class JavaCommercialPaper implements Contract { } @NotNull - public PublicKey getOwner() { + public AbstractParty getOwner() { return owner; } @@ -117,12 +120,12 @@ public class JavaCommercialPaper implements Contract { } public State withoutOwner() { - return new State(issuance, NullPublicKey.INSTANCE, faceValue, maturityDate); + return new State(issuance, new AnonymousParty(NullPublicKey.INSTANCE), faceValue, maturityDate); } @NotNull @Override - public List getParticipants() { + public List getParticipants() { return ImmutableList.of(this.owner); } } @@ -162,12 +165,12 @@ public class JavaCommercialPaper implements Contract { @NotNull List inputs, @NotNull List outputs, @NotNull List> commands, - @NotNull State groupingKey) { + State groupingKey) { AuthenticatedObject cmd = requireSingleCommand(tx.getCommands(), Commands.Move.class); // There should be only a single input due to aggregation above State input = single(inputs); - if (!cmd.getSigners().contains(input.getOwner())) + if (!cmd.getSigners().contains(input.getOwner().getOwningKey())) throw new IllegalStateException("Failed requirement: the transaction is signed by the owner of the CP"); // Check the output CP state is the same as the input state, ignoring the owner field. @@ -194,13 +197,13 @@ public class JavaCommercialPaper implements Contract { @NotNull List inputs, @NotNull List outputs, @NotNull List> commands, - @NotNull State groupingKey) { + State groupingKey) { AuthenticatedObject cmd = requireSingleCommand(tx.getCommands(), Commands.Redeem.class); // There should be only a single input due to aggregation above State input = single(inputs); - if (!cmd.getSigners().contains(input.getOwner())) + if (!cmd.getSigners().contains(input.getOwner().getOwningKey())) throw new IllegalStateException("Failed requirement: the transaction is signed by the owner of the CP"); Timestamp timestamp = tx.getTimestamp(); @@ -237,7 +240,7 @@ public class JavaCommercialPaper implements Contract { @NotNull List inputs, @NotNull List outputs, @NotNull List> commands, - @NotNull State groupingKey) { + State groupingKey) { AuthenticatedObject cmd = requireSingleCommand(tx.getCommands(), Commands.Issue.class); State output = single(outputs); Timestamp timestampCommand = tx.getTimestamp(); @@ -304,7 +307,7 @@ public class JavaCommercialPaper implements Contract { } public TransactionBuilder generateIssue(@NotNull PartyAndReference issuance, @NotNull Amount> faceValue, @Nullable Instant maturityDate, @NotNull Party notary, Integer encumbrance) { - State state = new State(issuance, issuance.getParty().getOwningKey(), faceValue, maturityDate); + State state = new State(issuance, issuance.getParty(), faceValue, maturityDate); TransactionState output = new TransactionState<>(state, notary, encumbrance); return new TransactionType.General.Builder(notary).withItems(output, new Command(new Commands.Issue(), issuance.getParty().getOwningKey())); } @@ -317,12 +320,12 @@ public class JavaCommercialPaper implements Contract { public void generateRedeem(TransactionBuilder tx, StateAndRef paper, VaultService vault) throws InsufficientBalanceException { vault.generateSpend(tx, StructuresKt.withoutIssuer(paper.getState().getData().getFaceValue()), paper.getState().getData().getOwner(), null); tx.addInputState(paper); - tx.addCommand(new Command(new Commands.Redeem(), paper.getState().getData().getOwner())); + tx.addCommand(new Command(new Commands.Redeem(), paper.getState().getData().getOwner().getOwningKey())); } - public void generateMove(TransactionBuilder tx, StateAndRef paper, PublicKey newOwner) { + public void generateMove(TransactionBuilder tx, StateAndRef paper, AbstractParty newOwner) { tx.addInputState(paper); tx.addOutputState(new TransactionState<>(new State(paper.getState().getData().getIssuance(), newOwner, paper.getState().getData().getFaceValue(), paper.getState().getData().getMaturityDate()), paper.getState().getNotary(), paper.getState().getEncumbrance())); - tx.addCommand(new Command(new Commands.Move(), paper.getState().getData().getOwner())); + tx.addCommand(new Command(new Commands.Move(), paper.getState().getData().getOwner().getOwningKey())); } } diff --git a/finance/src/main/kotlin/net/corda/contracts/CommercialPaper.kt b/finance/src/main/kotlin/net/corda/contracts/CommercialPaper.kt index 5719c292d2..38c637ea1a 100644 --- a/finance/src/main/kotlin/net/corda/contracts/CommercialPaper.kt +++ b/finance/src/main/kotlin/net/corda/contracts/CommercialPaper.kt @@ -10,6 +10,7 @@ import net.corda.core.contracts.clauses.GroupClauseVerifier import net.corda.core.contracts.clauses.verifyClause import net.corda.core.crypto.SecureHash import net.corda.core.crypto.toBase58String +import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.node.services.VaultService import net.corda.core.random63BitValue @@ -19,7 +20,6 @@ import net.corda.core.schemas.QueryableState import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.Emoji import net.corda.schemas.CommercialPaperSchemaV1 -import java.security.PublicKey import java.time.Instant import java.util.* @@ -61,22 +61,22 @@ class CommercialPaper : Contract { data class State( val issuance: PartyAndReference, - override val owner: PublicKey, + override val owner: AbstractParty, val faceValue: Amount>, val maturityDate: Instant ) : OwnableState, QueryableState, ICommercialPaperState { override val contract = CP_PROGRAM_ID - override val participants: List + override val participants: List get() = listOf(owner) val token: Issued get() = Issued(issuance, Terms(faceValue.token, maturityDate)) - override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner)) + override fun withNewOwner(newOwner: AbstractParty) = Pair(Commands.Move(), copy(owner = newOwner)) override fun toString() = "${Emoji.newspaper}CommercialPaper(of $faceValue redeemable on $maturityDate by '$issuance', owned by $owner)" // Although kotlin is smart enough not to need these, as we are using the ICommercialPaperState, we need to declare them explicitly for use later, - override fun withOwner(newOwner: PublicKey): ICommercialPaperState = copy(owner = newOwner) + override fun withOwner(newOwner: AbstractParty): ICommercialPaperState = copy(owner = newOwner) override fun withFaceValue(newFaceValue: Amount>): ICommercialPaperState = copy(faceValue = newFaceValue) override fun withMaturityDate(newMaturityDate: Instant): ICommercialPaperState = copy(maturityDate = newMaturityDate) @@ -91,7 +91,7 @@ class CommercialPaper : Contract { is CommercialPaperSchemaV1 -> CommercialPaperSchemaV1.PersistentCommercialPaperState( issuanceParty = this.issuance.party.owningKey.toBase58String(), issuanceRef = this.issuance.reference.bytes, - owner = this.owner.toBase58String(), + owner = this.owner.owningKey.toBase58String(), maturity = this.maturityDate, faceValue = this.faceValue.quantity, currency = this.faceValue.token.product.currencyCode, @@ -146,7 +146,7 @@ class CommercialPaper : Contract { val command = commands.requireSingleCommand() val input = inputs.single() requireThat { - "the transaction is signed by the owner of the CP" using (input.owner in command.signers) + "the transaction is signed by the owner of the CP" using (input.owner.owningKey in command.signers) "the state is propagated" using (outputs.size == 1) // Don't need to check anything else, as if outputs.size == 1 then the output is equal to // the input ignoring the owner field due to the grouping. @@ -175,7 +175,7 @@ class CommercialPaper : Contract { "the paper must have matured" using (time >= input.maturityDate) "the received amount equals the face value" using (received == input.faceValue) "the paper must be destroyed" using outputs.isEmpty() - "the transaction is signed by the owner of the CP" using (input.owner in command.signers) + "the transaction is signed by the owner of the CP" using (input.owner.owningKey in command.signers) } return setOf(command.value) @@ -196,17 +196,17 @@ class CommercialPaper : Contract { * at the moment: this restriction is not fundamental and may be lifted later. */ fun generateIssue(issuance: PartyAndReference, faceValue: Amount>, maturityDate: Instant, notary: Party): TransactionBuilder { - val state = TransactionState(State(issuance, issuance.party.owningKey, faceValue, maturityDate), notary) + val state = TransactionState(State(issuance, issuance.party, faceValue, maturityDate), notary) return TransactionType.General.Builder(notary = notary).withItems(state, Command(Commands.Issue(), issuance.party.owningKey)) } /** * Updates the given partial transaction with an input/output/command to reassign ownership of the paper. */ - fun generateMove(tx: TransactionBuilder, paper: StateAndRef, newOwner: PublicKey) { + fun generateMove(tx: TransactionBuilder, paper: StateAndRef, newOwner: AbstractParty) { tx.addInputState(paper) tx.addOutputState(TransactionState(paper.state.data.copy(owner = newOwner), paper.state.notary)) - tx.addCommand(Commands.Move(), paper.state.data.owner) + tx.addCommand(Commands.Move(), paper.state.data.owner.owningKey) } /** @@ -223,12 +223,12 @@ class CommercialPaper : Contract { val amount = paper.state.data.faceValue.let { amount -> Amount(amount.quantity, amount.token.product) } vault.generateSpend(tx, amount, paper.state.data.owner) tx.addInputState(paper) - tx.addCommand(CommercialPaper.Commands.Redeem(), paper.state.data.owner) + tx.addCommand(CommercialPaper.Commands.Redeem(), paper.state.data.owner.owningKey) } } -infix fun CommercialPaper.State.`owned by`(owner: PublicKey) = copy(owner = owner) +infix fun CommercialPaper.State.`owned by`(owner: AbstractParty) = copy(owner = owner) infix fun CommercialPaper.State.`with notary`(notary: Party) = TransactionState(this, notary) -infix fun ICommercialPaperState.`owned by`(newOwner: PublicKey) = withOwner(newOwner) +infix fun ICommercialPaperState.`owned by`(newOwner: AbstractParty) = withOwner(newOwner) diff --git a/finance/src/main/kotlin/net/corda/contracts/CommercialPaperLegacy.kt b/finance/src/main/kotlin/net/corda/contracts/CommercialPaperLegacy.kt index f46d777b1d..7be5b921f4 100644 --- a/finance/src/main/kotlin/net/corda/contracts/CommercialPaperLegacy.kt +++ b/finance/src/main/kotlin/net/corda/contracts/CommercialPaperLegacy.kt @@ -3,13 +3,13 @@ package net.corda.contracts import co.paralleluniverse.fibers.Suspendable import net.corda.contracts.asset.sumCashBy import net.corda.core.contracts.* -import net.corda.core.crypto.NullPublicKey +import net.corda.core.crypto.NULL_PARTY import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.node.services.VaultService import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.Emoji -import java.security.PublicKey import java.time.Instant import java.util.* @@ -27,19 +27,19 @@ class CommercialPaperLegacy : Contract { data class State( val issuance: PartyAndReference, - override val owner: PublicKey, + override val owner: AbstractParty, val faceValue: Amount>, val maturityDate: Instant ) : OwnableState, ICommercialPaperState { override val contract = CP_LEGACY_PROGRAM_ID override val participants = listOf(owner) - fun withoutOwner() = copy(owner = NullPublicKey) - override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner)) + fun withoutOwner() = copy(owner = NULL_PARTY) + override fun withNewOwner(newOwner: AbstractParty) = Pair(Commands.Move(), copy(owner = newOwner)) override fun toString() = "${Emoji.newspaper}CommercialPaper(of $faceValue redeemable on $maturityDate by '$issuance', owned by $owner)" // Although kotlin is smart enough not to need these, as we are using the ICommercialPaperState, we need to declare them explicitly for use later, - override fun withOwner(newOwner: PublicKey): ICommercialPaperState = copy(owner = newOwner) + override fun withOwner(newOwner: AbstractParty): ICommercialPaperState = copy(owner = newOwner) override fun withFaceValue(newFaceValue: Amount>): ICommercialPaperState = copy(faceValue = newFaceValue) override fun withMaturityDate(newMaturityDate: Instant): ICommercialPaperState = copy(maturityDate = newMaturityDate) @@ -70,7 +70,7 @@ class CommercialPaperLegacy : Contract { is Commands.Move -> { val input = inputs.single() requireThat { - "the transaction is signed by the owner of the CP" using (input.owner in command.signers) + "the transaction is signed by the owner of the CP" using (input.owner.owningKey in command.signers) "the state is propagated" using (outputs.size == 1) // Don't need to check anything else, as if outputs.size == 1 then the output is equal to // the input ignoring the owner field due to the grouping. @@ -86,7 +86,7 @@ class CommercialPaperLegacy : Contract { "the paper must have matured" using (time >= input.maturityDate) "the received amount equals the face value" using (received == input.faceValue) "the paper must be destroyed" using outputs.isEmpty() - "the transaction is signed by the owner of the CP" using (input.owner in command.signers) + "the transaction is signed by the owner of the CP" using (input.owner.owningKey in command.signers) } } @@ -114,14 +114,14 @@ class CommercialPaperLegacy : Contract { fun generateIssue(issuance: PartyAndReference, faceValue: Amount>, maturityDate: Instant, notary: Party): TransactionBuilder { - val state = State(issuance, issuance.party.owningKey, faceValue, maturityDate) + val state = State(issuance, issuance.party, faceValue, maturityDate) return TransactionBuilder(notary = notary).withItems(state, Command(Commands.Issue(), issuance.party.owningKey)) } - fun generateMove(tx: TransactionBuilder, paper: StateAndRef, newOwner: PublicKey) { + fun generateMove(tx: TransactionBuilder, paper: StateAndRef, newOwner: AbstractParty) { tx.addInputState(paper) tx.addOutputState(paper.state.data.withOwner(newOwner)) - tx.addCommand(Command(Commands.Move(), paper.state.data.owner)) + tx.addCommand(Command(Commands.Move(), paper.state.data.owner.owningKey)) } @Throws(InsufficientBalanceException::class) @@ -130,6 +130,6 @@ class CommercialPaperLegacy : Contract { // Add the cash movement using the states in our vault. vault.generateSpend(tx, paper.state.data.faceValue.withoutIssuer(), paper.state.data.owner) tx.addInputState(paper) - tx.addCommand(Command(Commands.Redeem(), paper.state.data.owner)) + tx.addCommand(Command(Commands.Redeem(), paper.state.data.owner.owningKey)) } } diff --git a/finance/src/main/kotlin/net/corda/contracts/asset/Cash.kt b/finance/src/main/kotlin/net/corda/contracts/asset/Cash.kt index 3eb983e3d9..d063423ed5 100644 --- a/finance/src/main/kotlin/net/corda/contracts/asset/Cash.kt +++ b/finance/src/main/kotlin/net/corda/contracts/asset/Cash.kt @@ -20,7 +20,6 @@ import net.corda.core.utilities.Emoji import net.corda.schemas.CashSchemaV1 import org.bouncycastle.asn1.x500.X500Name import java.math.BigInteger -import java.security.PublicKey import java.util.* ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -87,27 +86,27 @@ class Cash : OnLedgerAsset() { override val amount: Amount>, /** There must be a MoveCommand signed by this key to claim the amount. */ - override val owner: PublicKey + override val owner: AbstractParty ) : FungibleAsset, QueryableState { - constructor(deposit: PartyAndReference, amount: Amount, owner: PublicKey) + constructor(deposit: PartyAndReference, amount: Amount, owner: AbstractParty) : this(Amount(amount.quantity, Issued(deposit, amount.token)), owner) - override val exitKeys = setOf(owner, amount.token.issuer.party.owningKey) + override val exitKeys = setOf(owner.owningKey, amount.token.issuer.party.owningKey) override val contract = CASH_PROGRAM_ID override val participants = listOf(owner) - override fun move(newAmount: Amount>, newOwner: PublicKey): FungibleAsset + override fun move(newAmount: Amount>, newOwner: AbstractParty): FungibleAsset = copy(amount = amount.copy(newAmount.quantity), owner = newOwner) override fun toString() = "${Emoji.bagOfCash}Cash($amount at ${amount.token.issuer} owned by $owner)" - override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner)) + override fun withNewOwner(newOwner: AbstractParty) = Pair(Commands.Move(), copy(owner = newOwner)) /** Object Relational Mapping support. */ override fun generateMappedObject(schema: MappedSchema): PersistentState { return when (schema) { is CashSchemaV1 -> CashSchemaV1.PersistentCashState( - owner = this.owner.toBase58String(), + owner = this.owner.owningKey.toBase58String(), pennies = this.amount.quantity, currency = this.amount.token.product.currencyCode, issuerParty = this.amount.token.issuer.party.owningKey.toBase58String(), @@ -148,16 +147,16 @@ class Cash : OnLedgerAsset() { /** * Puts together an issuance transaction from the given template, that starts out being owned by the given pubkey. */ - fun generateIssue(tx: TransactionBuilder, tokenDef: Issued, pennies: Long, owner: PublicKey, notary: Party) + fun generateIssue(tx: TransactionBuilder, tokenDef: Issued, pennies: Long, owner: AbstractParty, notary: Party) = generateIssue(tx, Amount(pennies, tokenDef), owner, notary) /** * Puts together an issuance transaction for the specified amount that starts out being owned by the given pubkey. */ - fun generateIssue(tx: TransactionBuilder, amount: Amount>, owner: PublicKey, notary: Party) + fun generateIssue(tx: TransactionBuilder, amount: Amount>, owner: AbstractParty, notary: Party) = generateIssue(tx, TransactionState(State(amount, owner), notary), generateIssueCommand()) - override fun deriveState(txState: TransactionState, amount: Amount>, owner: PublicKey) + override fun deriveState(txState: TransactionState, amount: Amount>, owner: AbstractParty) = txState.copy(data = txState.data.copy(amount = amount, owner = owner)) override fun generateExitCommand(amount: Amount>) = Commands.Exit(amount) @@ -175,7 +174,7 @@ class Cash : OnLedgerAsset() { * if there are none, or if any of the cash states cannot be added together (i.e. are * different currencies or issuers). */ -fun Iterable.sumCashBy(owner: PublicKey): Amount> = filterIsInstance().filter { it.owner == owner }.map { it.amount }.sumOrThrow() +fun Iterable.sumCashBy(owner: AbstractParty): Amount> = filterIsInstance().filter { it.owner == owner }.map { it.amount }.sumOrThrow() /** * Sums the cash states in the list, throwing an exception if there are none, or if any of the cash @@ -191,12 +190,12 @@ fun Iterable.sumCashOrZero(currency: Issued): Amount().map { it.amount }.sumOrZero(currency) } -fun Cash.State.ownedBy(owner: PublicKey) = copy(owner = owner) -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.ownedBy(owner: AbstractParty) = copy(owner = owner) +fun Cash.State.issuedBy(party: AbstractParty) = 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: PublicKey) = ownedBy(owner) +infix fun Cash.State.`owned by`(owner: AbstractParty) = ownedBy(owner) infix fun Cash.State.`issued by`(party: AbstractParty) = issuedBy(party) infix fun Cash.State.`issued by`(deposit: PartyAndReference) = issuedBy(deposit) infix fun Cash.State.`with deposit`(deposit: PartyAndReference): Cash.State = withDeposit(deposit) @@ -208,6 +207,6 @@ val DUMMY_CASH_ISSUER_KEY by lazy { entropyToKeyPair(BigInteger.valueOf(10)) } /** A dummy, randomly generated issuer party by the name of "Snake Oil Issuer" */ val DUMMY_CASH_ISSUER by lazy { Party(X500Name("CN=Snake Oil Issuer,O=R3,OU=corda,L=London,C=UK"), DUMMY_CASH_ISSUER_KEY.public).ref(1) } /** An extension property that lets you write 100.DOLLARS.CASH */ -val Amount.CASH: Cash.State get() = Cash.State(Amount(quantity, Issued(DUMMY_CASH_ISSUER, token)), NullPublicKey) -/** An extension property that lets you get a cash state from an issued token, under the [NullPublicKey] */ -val Amount>.STATE: Cash.State get() = Cash.State(this, NullPublicKey) +val Amount.CASH: Cash.State get() = Cash.State(Amount(quantity, Issued(DUMMY_CASH_ISSUER, token)), NULL_PARTY) +/** An extension property that lets you get a cash state from an issued token, under the [NULL_PARTY] */ +val Amount>.STATE: Cash.State get() = Cash.State(this, NULL_PARTY) diff --git a/finance/src/main/kotlin/net/corda/contracts/asset/CommodityContract.kt b/finance/src/main/kotlin/net/corda/contracts/asset/CommodityContract.kt index e47dd127c4..c8cadda2ef 100644 --- a/finance/src/main/kotlin/net/corda/contracts/asset/CommodityContract.kt +++ b/finance/src/main/kotlin/net/corda/contracts/asset/CommodityContract.kt @@ -9,10 +9,10 @@ import net.corda.core.contracts.clauses.GroupClauseVerifier import net.corda.core.contracts.clauses.verifyClause import net.corda.core.crypto.SecureHash import net.corda.core.crypto.newSecureRandom +import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.transactions.TransactionBuilder -import java.security.PublicKey import java.util.* ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -94,21 +94,21 @@ class CommodityContract : OnLedgerAsset>, /** There must be a MoveCommand signed by this key to claim the amount */ - override val owner: PublicKey + override val owner: AbstractParty ) : FungibleAsset { - constructor(deposit: PartyAndReference, amount: Amount, owner: PublicKey) + constructor(deposit: PartyAndReference, amount: Amount, owner: AbstractParty) : this(Amount(amount.quantity, Issued(deposit, amount.token)), owner) override val contract = COMMODITY_PROGRAM_ID - override val exitKeys = Collections.singleton(owner) + override val exitKeys = Collections.singleton(owner.owningKey) override val participants = listOf(owner) - override fun move(newAmount: Amount>, newOwner: PublicKey): FungibleAsset + override fun move(newAmount: Amount>, newOwner: AbstractParty): FungibleAsset = copy(amount = amount.copy(newAmount.quantity), owner = newOwner) override fun toString() = "Commodity($amount at ${amount.token.issuer} owned by $owner)" - override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner)) + override fun withNewOwner(newOwner: AbstractParty) = Pair(Commands.Move(), copy(owner = newOwner)) } // Just for grouping @@ -145,17 +145,17 @@ class CommodityContract : OnLedgerAsset, pennies: Long, owner: PublicKey, notary: Party) + fun generateIssue(tx: TransactionBuilder, tokenDef: Issued, pennies: Long, owner: AbstractParty, notary: Party) = generateIssue(tx, Amount(pennies, tokenDef), owner, notary) /** * Puts together an issuance transaction for the specified amount that starts out being owned by the given pubkey. */ - fun generateIssue(tx: TransactionBuilder, amount: Amount>, owner: PublicKey, notary: Party) + fun generateIssue(tx: TransactionBuilder, amount: Amount>, owner: AbstractParty, notary: Party) = generateIssue(tx, TransactionState(State(amount, owner), notary), generateIssueCommand()) - override fun deriveState(txState: TransactionState, amount: Amount>, owner: PublicKey) + override fun deriveState(txState: TransactionState, amount: Amount>, owner: AbstractParty) = txState.copy(data = txState.data.copy(amount = amount, owner = owner)) override fun generateExitCommand(amount: Amount>) = Commands.Exit(amount) diff --git a/finance/src/main/kotlin/net/corda/contracts/asset/Obligation.kt b/finance/src/main/kotlin/net/corda/contracts/asset/Obligation.kt index ba154e2225..9cb6508363 100644 --- a/finance/src/main/kotlin/net/corda/contracts/asset/Obligation.kt +++ b/finance/src/main/kotlin/net/corda/contracts/asset/Obligation.kt @@ -5,7 +5,9 @@ import net.corda.contracts.asset.Obligation.Lifecycle.NORMAL import net.corda.contracts.clause.* import net.corda.core.contracts.* import net.corda.core.contracts.clauses.* -import net.corda.core.crypto.* +import net.corda.core.crypto.NULL_PARTY +import net.corda.core.crypto.SecureHash +import net.corda.core.crypto.entropyToKeyPair import net.corda.core.identity.AbstractParty import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party @@ -22,6 +24,36 @@ import java.security.PublicKey import java.time.Duration import java.time.Instant import java.util.* +import kotlin.collections.Collection +import kotlin.collections.Iterable +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.Set +import kotlin.collections.all +import kotlin.collections.asIterable +import kotlin.collections.component1 +import kotlin.collections.component2 +import kotlin.collections.contains +import kotlin.collections.distinct +import kotlin.collections.emptySet +import kotlin.collections.filter +import kotlin.collections.filterIsInstance +import kotlin.collections.first +import kotlin.collections.firstOrNull +import kotlin.collections.forEach +import kotlin.collections.groupBy +import kotlin.collections.isNotEmpty +import kotlin.collections.iterator +import kotlin.collections.listOf +import kotlin.collections.map +import kotlin.collections.none +import kotlin.collections.reduce +import kotlin.collections.set +import kotlin.collections.setOf +import kotlin.collections.single +import kotlin.collections.toSet +import kotlin.collections.union +import kotlin.collections.withIndex // Just a fake program identifier for now. In a real system it could be, for instance, the hash of the program bytecode. val OBLIGATION_PROGRAM_ID = Obligation() @@ -274,27 +306,20 @@ class Obligation

: Contract { data class State

( var lifecycle: Lifecycle = Lifecycle.NORMAL, /** Where the debt originates from (obligor) */ - val obligor: AnonymousParty, + val obligor: AbstractParty, val template: Terms

, val quantity: Long, /** The public key of the entity the contract pays to */ - val beneficiary: PublicKey + val beneficiary: AbstractParty ) : FungibleAsset>, NettableState, MultilateralNetState

> { - constructor(lifecycle: Lifecycle = Lifecycle.NORMAL, - obligor: Party, - template: Terms

, - quantity: Long, - beneficiary: PublicKey) - : this(lifecycle, obligor.toAnonymous(), template, quantity, beneficiary) - override val amount: Amount>> = Amount(quantity, Issued(obligor.ref(0), template)) override val contract = OBLIGATION_PROGRAM_ID - override val exitKeys: Collection = setOf(beneficiary) + override val exitKeys: Collection = setOf(beneficiary.owningKey) val dueBefore: Instant = template.dueBefore - override val participants: List = listOf(obligor.owningKey, beneficiary) - override val owner: PublicKey = beneficiary + override val participants: List = listOf(obligor, beneficiary) + override val owner: AbstractParty = beneficiary - override fun move(newAmount: Amount>>, newOwner: PublicKey): State

+ override fun move(newAmount: Amount>>, newOwner: AbstractParty): State

= copy(quantity = newAmount.quantity, beneficiary = newOwner) override fun toString() = when (lifecycle) { @@ -305,7 +330,7 @@ class Obligation

: Contract { override val bilateralNetState: BilateralNetState

get() { check(lifecycle == Lifecycle.NORMAL) - return BilateralNetState(setOf(obligor.owningKey, beneficiary), template) + return BilateralNetState(setOf(obligor, beneficiary), template) } override val multilateralNetState: MultilateralNetState

get() { @@ -327,7 +352,7 @@ class Obligation

: Contract { } } - override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(beneficiary = newOwner)) + override fun withNewOwner(newOwner: AbstractParty) = Pair(Commands.Move(), copy(beneficiary = newOwner)) } // Just for grouping @@ -418,7 +443,7 @@ class Obligation

: Contract { } } } - val owningPubKeys = inputs.filter { it is State

}.map { (it as State

).beneficiary }.toSet() + val owningPubKeys = inputs.filter { it is State

}.map { (it as State

).beneficiary.owningKey }.toSet() val keysThatSigned = setLifecycleCommand.signers.toSet() requireThat { "the owning keys are a subset of the signing keys" using keysThatSigned.containsAll(owningPubKeys) @@ -433,7 +458,7 @@ class Obligation

: Contract { * and same parties involved). */ fun generateCloseOutNetting(tx: TransactionBuilder, - signer: PublicKey, + signer: AbstractParty, vararg states: State

) { val netState = states.firstOrNull()?.bilateralNetState @@ -447,7 +472,7 @@ class Obligation

: Contract { val out = states.reduce(State

::net) if (out.quantity > 0L) tx.addOutputState(out) - tx.addCommand(Commands.Net(NetType.PAYMENT), signer) + tx.addCommand(Commands.Net(NetType.PAYMENT), signer.owningKey) } /** @@ -475,9 +500,9 @@ class Obligation

: Contract { obligor: AbstractParty, issuanceDef: Terms

, pennies: Long, - beneficiary: PublicKey, + beneficiary: AbstractParty, notary: Party) - = OnLedgerAsset.generateIssue(tx, TransactionState(State(Lifecycle.NORMAL, obligor.toAnonymous(), issuanceDef, pennies, beneficiary), notary), Commands.Issue()) + = OnLedgerAsset.generateIssue(tx, TransactionState(State(Lifecycle.NORMAL, obligor, issuanceDef, pennies, beneficiary), notary), Commands.Issue()) fun generatePaymentNetting(tx: TransactionBuilder, issued: Issued>, @@ -487,8 +512,8 @@ class Obligation

: Contract { "all states are in the normal lifecycle state " using (states.all { it.lifecycle == Lifecycle.NORMAL }) } val groups = states.groupBy { it.multilateralNetState } - val partyLookup = HashMap() - val signers = states.map { it.beneficiary }.union(states.map { it.obligor.owningKey }).toSet() + val partyLookup = HashMap() + val signers = states.map { it.beneficiary }.union(states.map { it.obligor }).toSet() // Create a lookup table of the party that each public key represents. states.map { it.obligor }.forEach { partyLookup.put(it.owningKey, it) } @@ -502,12 +527,12 @@ class Obligation

: Contract { netBalances // Convert the balances into obligation state objects .map { entry -> - State(Lifecycle.NORMAL, partyLookup[entry.key.first]!!, + State(Lifecycle.NORMAL, entry.key.first, netState.template, entry.value.quantity, entry.key.second) } // Add the new states to the TX .forEach { tx.addOutputState(it, notary) } - tx.addCommand(Commands.Net(NetType.PAYMENT), signers.toList()) + tx.addCommand(Commands.Net(NetType.PAYMENT), signers.map { it.owningKey }) } } @@ -533,14 +558,14 @@ class Obligation

: Contract { // Produce a new set of states val groups = statesAndRefs.groupBy { it.state.data.amount.token } for ((_, stateAndRefs) in groups) { - val partiesUsed = ArrayList() + val partiesUsed = ArrayList() stateAndRefs.forEach { stateAndRef -> val outState = stateAndRef.state.data.copy(lifecycle = lifecycle) tx.addInputState(stateAndRef) tx.addOutputState(outState, notary) partiesUsed.add(stateAndRef.state.data.beneficiary) } - tx.addCommand(Commands.SetLifecycle(lifecycle), partiesUsed.distinct()) + tx.addCommand(Commands.SetLifecycle(lifecycle), partiesUsed.map { it.owningKey }.distinct()) } tx.setTime(issuanceDef.dueBefore, issuanceDef.timeTolerance) } @@ -578,7 +603,7 @@ class Obligation

: Contract { val template: Terms

= issuanceDef.product val obligationTotal: Amount

= Amount(states.map { it.data }.sumObligations

().quantity, template.product) var obligationRemaining: Amount

= obligationTotal - val assetSigners = HashSet() + val assetSigners = HashSet() statesAndRefs.forEach { tx.addInputState(it) } @@ -611,7 +636,7 @@ class Obligation

: Contract { } // Add the asset move command and obligation settle - tx.addCommand(moveCommand, assetSigners.toList()) + tx.addCommand(moveCommand, assetSigners.map { it.owningKey }) tx.addCommand(Commands.Settle(Amount((obligationTotal - obligationRemaining).quantity, issuanceDef)), obligationIssuer.owningKey) } @@ -630,11 +655,11 @@ class Obligation

: Contract { * * @return a map of obligor/beneficiary pairs to the balance due. */ -fun

extractAmountsDue(product: Obligation.Terms

, states: Iterable>): Map, Amount>> { - val balances = HashMap, Amount>>() +fun

extractAmountsDue(product: Obligation.Terms

, states: Iterable>): Map, Amount>> { + val balances = HashMap, Amount>>() states.forEach { state -> - val key = Pair(state.obligor.owningKey, state.beneficiary) + val key = Pair(state.obligor, state.beneficiary) val balance = balances[key] ?: Amount(0L, product) balances[key] = balance + Amount(state.amount.quantity, state.amount.token.product) } @@ -645,8 +670,8 @@ fun

extractAmountsDue(product: Obligation.Terms

, states: Iterable netAmountsDue(balances: Map, Amount

>): Map, Amount

> { - val nettedBalances = HashMap, Amount

>() +fun netAmountsDue(balances: Map, Amount>): Map, Amount> { + val nettedBalances = HashMap, Amount>() balances.forEach { balance -> val (obligor, beneficiary) = balance.key @@ -669,9 +694,11 @@ fun

netAmountsDue(balances: Map, Amount

> * * @param balances payments due, indexed by obligor and beneficiary. Zero balances are stripped from the map before being * returned. + * @param P type of party to operate on. + * @param T token that balances represent */ -fun

sumAmountsDue(balances: Map, Amount

>): Map { - val sum = HashMap() +fun sumAmountsDue(balances: Map, Amount>): Map { + val sum = HashMap() // Fill the map with zeroes initially balances.keys.forEach { @@ -712,11 +739,11 @@ fun

Iterable.sumObligationsOrZero(issuanceDef: Issued>().filter { it.lifecycle == Obligation.Lifecycle.NORMAL }.map { it.amount }.sumOrZero(issuanceDef) infix fun Obligation.State.at(dueBefore: Instant) = copy(template = template.copy(dueBefore = dueBefore)) -infix fun Obligation.State.between(parties: Pair) = copy(obligor = parties.first.toAnonymous(), beneficiary = parties.second) -infix fun Obligation.State.`owned by`(owner: PublicKey) = copy(beneficiary = owner) -infix fun Obligation.State.`issued by`(party: AbstractParty) = copy(obligor = party.toAnonymous()) +infix fun Obligation.State.between(parties: Pair) = copy(obligor = parties.first, beneficiary = parties.second) +infix fun Obligation.State.`owned by`(owner: AbstractParty) = copy(beneficiary = owner) +infix fun Obligation.State.`issued by`(party: AbstractParty) = copy(obligor = party) // For Java users: -@Suppress("unused") fun Obligation.State.ownedBy(owner: PublicKey) = copy(beneficiary = owner) +@Suppress("unused") fun Obligation.State.ownedBy(owner: AbstractParty) = copy(beneficiary = owner) @Suppress("unused") fun Obligation.State.issuedBy(party: AnonymousParty) = copy(obligor = party) @@ -728,4 +755,4 @@ val DUMMY_OBLIGATION_ISSUER by lazy { Party(X500Name("CN=Snake Oil Issuer,O=R3,O val Issued.OBLIGATION_DEF: Obligation.Terms get() = Obligation.Terms(nonEmptySetOf(Cash().legalContractReference), nonEmptySetOf(this), TEST_TX_TIME) val Amount>.OBLIGATION: Obligation.State - get() = Obligation.State(Obligation.Lifecycle.NORMAL, DUMMY_OBLIGATION_ISSUER.toAnonymous(), token.OBLIGATION_DEF, quantity, NullPublicKey) + get() = Obligation.State(Obligation.Lifecycle.NORMAL, DUMMY_OBLIGATION_ISSUER, token.OBLIGATION_DEF, quantity, NULL_PARTY) diff --git a/finance/src/main/kotlin/net/corda/contracts/asset/OnLedgerAsset.kt b/finance/src/main/kotlin/net/corda/contracts/asset/OnLedgerAsset.kt index 47f286dece..175182d48a 100644 --- a/finance/src/main/kotlin/net/corda/contracts/asset/OnLedgerAsset.kt +++ b/finance/src/main/kotlin/net/corda/contracts/asset/OnLedgerAsset.kt @@ -1,7 +1,7 @@ package net.corda.contracts.asset -import net.corda.contracts.clause.AbstractConserveAmount import net.corda.core.contracts.* +import net.corda.core.identity.AbstractParty import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.loggerFor import net.corda.core.utilities.trace @@ -51,9 +51,9 @@ abstract class OnLedgerAsset> : C @JvmStatic fun , T: Any> generateSpend(tx: TransactionBuilder, amount: Amount, - to: PublicKey, + to: AbstractParty, acceptableStates: List>, - deriveState: (TransactionState, Amount>, PublicKey) -> TransactionState, + deriveState: (TransactionState, Amount>, AbstractParty) -> TransactionState, generateMoveCommand: () -> CommandData): Pair> { // Discussion // @@ -90,7 +90,7 @@ abstract class OnLedgerAsset> : C } else { null } - val keysUsed = gathered.map { it.state.data.owner } + val keysUsed = gathered.map { it.state.data.owner.owningKey } val states = gathered.groupBy { it.state.data.amount.token.issuer }.map { val coins = it.value @@ -165,7 +165,7 @@ abstract class OnLedgerAsset> : C @JvmStatic fun , T: Any> generateExit(tx: TransactionBuilder, amountIssued: Amount>, assetStates: List>, - deriveState: (TransactionState, Amount>, PublicKey) -> TransactionState, + deriveState: (TransactionState, Amount>, AbstractParty) -> TransactionState, generateMoveCommand: () -> CommandData, generateExitCommand: (Amount>) -> CommandData): PublicKey { val owner = assetStates.map { it.state.data.owner }.toSet().singleOrNull() ?: throw InsufficientBalanceException(amountIssued) @@ -193,7 +193,7 @@ abstract class OnLedgerAsset> : C for (state in gathered) tx.addInputState(state) for (state in outputs) tx.addOutputState(state) - tx.addCommand(generateMoveCommand(), gathered.map { it.state.data.owner }) + tx.addCommand(generateMoveCommand(), gathered.map { it.state.data.owner.owningKey }) tx.addCommand(generateExitCommand(amountIssued), gathered.flatMap { it.state.data.exitKeys }) return amountIssued.token.issuer.party.owningKey } @@ -250,5 +250,5 @@ abstract class OnLedgerAsset> : C * implementations to have fields in their state which we don't know about here, and we simply leave them untouched * when sending out "change" from spending/exiting. */ - abstract fun deriveState(txState: TransactionState, amount: Amount>, owner: PublicKey): TransactionState + abstract fun deriveState(txState: TransactionState, amount: Amount>, owner: AbstractParty): TransactionState } diff --git a/finance/src/main/kotlin/net/corda/contracts/clause/AbstractConserveAmount.kt b/finance/src/main/kotlin/net/corda/contracts/clause/AbstractConserveAmount.kt index dde9354f9d..c48386cd1e 100644 --- a/finance/src/main/kotlin/net/corda/contracts/clause/AbstractConserveAmount.kt +++ b/finance/src/main/kotlin/net/corda/contracts/clause/AbstractConserveAmount.kt @@ -3,6 +3,7 @@ package net.corda.contracts.clause import net.corda.contracts.asset.OnLedgerAsset import net.corda.core.contracts.* import net.corda.core.contracts.clauses.Clause +import net.corda.core.identity.AbstractParty import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.loggerFor import java.security.PublicKey @@ -31,7 +32,7 @@ abstract class AbstractConserveAmount, C : CommandData, T : @Throws(InsufficientBalanceException::class) fun generateExit(tx: TransactionBuilder, amountIssued: Amount>, assetStates: List>, - deriveState: (TransactionState, Amount>, PublicKey) -> TransactionState, + deriveState: (TransactionState, Amount>, AbstractParty) -> TransactionState, generateMoveCommand: () -> CommandData, generateExitCommand: (Amount>) -> CommandData): PublicKey = OnLedgerAsset.generateExit(tx, amountIssued, assetStates, deriveState, generateMoveCommand, generateExitCommand) diff --git a/finance/src/main/kotlin/net/corda/contracts/clause/Net.kt b/finance/src/main/kotlin/net/corda/contracts/clause/Net.kt index 452dded632..5eee72380e 100644 --- a/finance/src/main/kotlin/net/corda/contracts/clause/Net.kt +++ b/finance/src/main/kotlin/net/corda/contracts/clause/Net.kt @@ -6,6 +6,7 @@ import net.corda.contracts.asset.extractAmountsDue import net.corda.contracts.asset.sumAmountsDue import net.corda.core.contracts.* import net.corda.core.contracts.clauses.Clause +import net.corda.core.identity.AbstractParty import java.security.PublicKey /** @@ -22,7 +23,7 @@ interface NetState

{ * Bilateral states are used in close-out netting. */ data class BilateralNetState

( - val partyKeys: Set, + val partyKeys: Set, override val template: Obligation.Terms

) : NetState

@@ -86,7 +87,7 @@ open class NetClause : Clause( } // TODO: Handle proxies nominated by parties, i.e. a central clearing service - val involvedParties = inputs.map { it.beneficiary }.union(inputs.map { it.obligor.owningKey }).toSet() + val involvedParties: Set = inputs.map { it.beneficiary.owningKey }.union(inputs.map { it.obligor.owningKey }).toSet() when (command.value.type) { // For close-out netting, allow any involved party to sign NetType.CLOSE_OUT -> require(command.signers.intersect(involvedParties).isNotEmpty()) { "any involved party has signed" } diff --git a/finance/src/main/kotlin/net/corda/contracts/testing/DummyDealContract.kt b/finance/src/main/kotlin/net/corda/contracts/testing/DummyDealContract.kt index a32fe333f1..5e21ed316b 100644 --- a/finance/src/main/kotlin/net/corda/contracts/testing/DummyDealContract.kt +++ b/finance/src/main/kotlin/net/corda/contracts/testing/DummyDealContract.kt @@ -5,6 +5,7 @@ import net.corda.core.contracts.DealState import net.corda.core.contracts.TransactionForContract import net.corda.core.contracts.UniqueIdentifier import net.corda.core.crypto.* +import net.corda.core.identity.AbstractParty import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import net.corda.core.transactions.TransactionBuilder @@ -17,12 +18,12 @@ class DummyDealContract : Contract { data class State( override val contract: Contract = DummyDealContract(), - override val participants: List = listOf(), + override val participants: List = listOf(), override val linearId: UniqueIdentifier = UniqueIdentifier(), override val ref: String, override val parties: List = listOf()) : DealState { override fun isRelevant(ourKeys: Set): Boolean { - return participants.any { it.containsAny(ourKeys) } + return participants.any { it.owningKey.containsAny(ourKeys) } } override fun generateAgreement(notary: Party): TransactionBuilder { diff --git a/finance/src/main/kotlin/net/corda/contracts/testing/DummyLinearContract.kt b/finance/src/main/kotlin/net/corda/contracts/testing/DummyLinearContract.kt index 3671bf637d..6809dec4fd 100644 --- a/finance/src/main/kotlin/net/corda/contracts/testing/DummyLinearContract.kt +++ b/finance/src/main/kotlin/net/corda/contracts/testing/DummyLinearContract.kt @@ -4,9 +4,9 @@ import net.corda.core.contracts.* import net.corda.core.contracts.clauses.Clause import net.corda.core.contracts.clauses.FilterOn import net.corda.core.contracts.clauses.verifyClause -import net.corda.core.crypto.CompositeKey import net.corda.core.crypto.SecureHash import net.corda.core.crypto.containsAny +import net.corda.core.identity.AbstractParty import java.security.PublicKey class DummyLinearContract : Contract { @@ -20,11 +20,11 @@ class DummyLinearContract : Contract { data class State( override val linearId: UniqueIdentifier = UniqueIdentifier(), override val contract: Contract = DummyLinearContract(), - override val participants: List = listOf(), + override val participants: List = listOf(), val nonce: SecureHash = SecureHash.randomSHA256()) : LinearState { override fun isRelevant(ourKeys: Set): Boolean { - return participants.any { it.containsAny(ourKeys) } + return participants.any { it.owningKey.containsAny(ourKeys) } } } } \ No newline at end of file diff --git a/finance/src/main/kotlin/net/corda/contracts/testing/VaultFiller.kt b/finance/src/main/kotlin/net/corda/contracts/testing/VaultFiller.kt index 89efaa400d..720e2214a3 100644 --- a/finance/src/main/kotlin/net/corda/contracts/testing/VaultFiller.kt +++ b/finance/src/main/kotlin/net/corda/contracts/testing/VaultFiller.kt @@ -6,7 +6,8 @@ import net.corda.contracts.asset.Cash import net.corda.contracts.asset.DUMMY_CASH_ISSUER import net.corda.contracts.asset.DUMMY_CASH_ISSUER_KEY import net.corda.core.contracts.* -import net.corda.core.crypto.CompositeKey +import net.corda.core.identity.AbstractParty +import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import net.corda.core.node.ServiceHub import net.corda.core.node.services.Vault @@ -21,13 +22,15 @@ import java.util.* @JvmOverloads fun ServiceHub.fillWithSomeTestDeals(dealIds: List, revisions: Int? = 0, - participants: List = emptyList()) : Vault { + participants: List = emptyList()) : Vault { val freshKey = keyManagementService.freshKey() + val freshPublicKey = freshKey.public + val recipient = AnonymousParty(freshPublicKey) val transactions: List = dealIds.map { // Issue a deal state val dummyIssue = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply { - addOutputState(DummyDealContract.State(ref = it, participants = participants.plus(freshKey.public))) + addOutputState(DummyDealContract.State(ref = it, participants = participants.plus(recipient))) signWith(freshKey) signWith(DUMMY_NOTARY_KEY) } @@ -47,13 +50,15 @@ fun ServiceHub.fillWithSomeTestDeals(dealIds: List, @JvmOverloads fun ServiceHub.fillWithSomeTestLinearStates(numberToCreate: Int, uid: UniqueIdentifier = UniqueIdentifier(), - participants: List = emptyList()) : Vault { + participants: List = emptyList()) : Vault { val freshKey = keyManagementService.freshKey() + val freshPublicKey = freshKey.public + val recipient = AnonymousParty(freshPublicKey) val transactions: List = (1..numberToCreate).map { // Issue a Linear state val dummyIssue = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply { - addOutputState(DummyLinearContract.State(linearId = uid, participants = participants.plus(freshKey.public))) + addOutputState(DummyLinearContract.State(linearId = uid, participants = participants.plus(recipient))) signWith(freshKey) signWith(DUMMY_NOTARY_KEY) } @@ -87,18 +92,19 @@ fun ServiceHub.fillWithSomeTestCash(howMuch: Amount, atMostThisManyStates: Int = 10, rng: Random = Random(), ref: OpaqueBytes = OpaqueBytes(ByteArray(1, { 1 })), - ownedBy: PublicKey? = null, + ownedBy: AbstractParty? = null, issuedBy: PartyAndReference = DUMMY_CASH_ISSUER, issuerKey: KeyPair = DUMMY_CASH_ISSUER_KEY): Vault { val amounts = calculateRandomlySizedAmounts(howMuch, atLeastThisManyStates, atMostThisManyStates, rng) - val myKey: PublicKey = ownedBy ?: myInfo.legalIdentity.owningKey + val myKey: PublicKey = ownedBy?.owningKey ?: myInfo.legalIdentity.owningKey + val me = AnonymousParty(myKey) // We will allocate one state to one transaction, for simplicities sake. val cash = Cash() val transactions: List = amounts.map { pennies -> val issuance = TransactionType.General.Builder(null) - cash.generateIssue(issuance, Amount(pennies, Issued(issuedBy.copy(reference = ref), howMuch.token)), myKey, outputNotary) + cash.generateIssue(issuance, Amount(pennies, Issued(issuedBy.copy(reference = ref), howMuch.token)), me, outputNotary) issuance.signWith(issuerKey) return@map issuance.toSignedTransaction(true) diff --git a/finance/src/main/kotlin/net/corda/flows/CashExitFlow.kt b/finance/src/main/kotlin/net/corda/flows/CashExitFlow.kt index d87d4cfeb5..9ac53024e2 100644 --- a/finance/src/main/kotlin/net/corda/flows/CashExitFlow.kt +++ b/finance/src/main/kotlin/net/corda/flows/CashExitFlow.kt @@ -60,7 +60,7 @@ class CashExitFlow(val amount: Amount, val issueRef: OpaqueBytes, prog // count as a reason to fail? val participants: Set = inputStates .filterIsInstance() - .map { serviceHub.identityService.partyFromKey(it.owner) } + .map { serviceHub.identityService.partyFromAnonymous(it.owner) } .filterNotNull() .toSet() diff --git a/finance/src/main/kotlin/net/corda/flows/CashIssueFlow.kt b/finance/src/main/kotlin/net/corda/flows/CashIssueFlow.kt index a90667ff71..f53856927f 100644 --- a/finance/src/main/kotlin/net/corda/flows/CashIssueFlow.kt +++ b/finance/src/main/kotlin/net/corda/flows/CashIssueFlow.kt @@ -37,7 +37,8 @@ class CashIssueFlow(val amount: Amount, progressTracker.currentStep = GENERATING_TX val builder: TransactionBuilder = TransactionType.General.Builder(notary = null) val issuer = serviceHub.myInfo.legalIdentity.ref(issueRef) - Cash().generateIssue(builder, amount.issuedBy(issuer), recipient.owningKey, notary) + // TODO: Get a transaction key, don't just re-use the owning key + Cash().generateIssue(builder, amount.issuedBy(issuer), recipient, notary) progressTracker.currentStep = SIGNING_TX val myKey = serviceHub.legalIdentityKey builder.signWith(myKey) diff --git a/finance/src/main/kotlin/net/corda/flows/CashPaymentFlow.kt b/finance/src/main/kotlin/net/corda/flows/CashPaymentFlow.kt index ff6fe84355..b348d4f8bb 100644 --- a/finance/src/main/kotlin/net/corda/flows/CashPaymentFlow.kt +++ b/finance/src/main/kotlin/net/corda/flows/CashPaymentFlow.kt @@ -39,7 +39,8 @@ open class CashPaymentFlow( serviceHub.vaultService.generateSpend( builder, amount, - recipient.owningKey, + // TODO: Get a transaction key, don't just re-use the owning key + recipient, issuerConstraint) } catch (e: InsufficientBalanceException) { throw CashException("Insufficient cash for spend: ${e.message}", e) diff --git a/finance/src/main/kotlin/net/corda/flows/TwoPartyTradeFlow.kt b/finance/src/main/kotlin/net/corda/flows/TwoPartyTradeFlow.kt index 7d5838c888..0710534001 100644 --- a/finance/src/main/kotlin/net/corda/flows/TwoPartyTradeFlow.kt +++ b/finance/src/main/kotlin/net/corda/flows/TwoPartyTradeFlow.kt @@ -8,6 +8,7 @@ import net.corda.core.crypto.expandedCompositeKeys import net.corda.core.crypto.sign import net.corda.core.flows.FlowException import net.corda.core.flows.FlowLogic +import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import net.corda.core.node.NodeInfo import net.corda.core.seconds @@ -34,7 +35,7 @@ import java.util.* * 3. S signs it and commits it to the ledger, notarising it and distributing the final signed transaction back * to B. * - * Assuming no malicious termination, they both end the flow being in posession of a valid, signed transaction + * Assuming no malicious termination, they both end the flow being in possession of a valid, signed transaction * that represents an atomic asset swap. * * Note that it's the *seller* who initiates contact with the buyer, not vice-versa as you might imagine. @@ -118,7 +119,7 @@ object TwoPartyTradeFlow { // even though it is missing signatures. subFlow(ResolveTransactionsFlow(wtx, otherParty)) - if (wtx.outputs.map { it.data }.sumCashBy(myPublicKey).withoutIssuer() != price) + if (wtx.outputs.map { it.data }.sumCashBy(AnonymousParty(myPublicKey)).withoutIssuer() != price) throw FlowException("Transaction is not sending us the right amount of cash") it @@ -219,7 +220,7 @@ object TwoPartyTradeFlow { val ptx = TransactionType.General.Builder(notary) // Add input and output states for the movement of cash, by using the Cash contract to generate the states - val (tx, cashSigningPubKeys) = serviceHub.vaultService.generateSpend(ptx, tradeRequest.price, tradeRequest.sellerOwnerKey) + val (tx, cashSigningPubKeys) = serviceHub.vaultService.generateSpend(ptx, tradeRequest.price, AnonymousParty(tradeRequest.sellerOwnerKey)) // Add inputs/outputs/a command for the movement of the asset. tx.addInputState(tradeRequest.assetForSale) @@ -228,10 +229,10 @@ object TwoPartyTradeFlow { // we want for privacy reasons: the key is here ONLY to manage and control ownership, it is not intended to // reveal who the owner actually is. The key management service is expected to derive a unique key from some // initial seed in order to provide privacy protection. - val freshKey = serviceHub.keyManagementService.freshKey() - val (command, state) = tradeRequest.assetForSale.state.data.withNewOwner(freshKey.public) + val freshPublicKey = serviceHub.keyManagementService.freshKey().public + val (command, state) = tradeRequest.assetForSale.state.data.withNewOwner(AnonymousParty(freshPublicKey)) tx.addOutputState(state, tradeRequest.assetForSale.state.notary) - tx.addCommand(command, tradeRequest.assetForSale.state.data.owner) + tx.addCommand(command, tradeRequest.assetForSale.state.data.owner.owningKey) // And add a request for timestamping: it may be that none of the contracts need this! But it can't hurt // to have one. diff --git a/finance/src/test/java/net/corda/contracts/asset/CashTestsJava.java b/finance/src/test/java/net/corda/contracts/asset/CashTestsJava.java index 866172402c..2c8b2d4595 100644 --- a/finance/src/test/java/net/corda/contracts/asset/CashTestsJava.java +++ b/finance/src/test/java/net/corda/contracts/asset/CashTestsJava.java @@ -1,12 +1,15 @@ package net.corda.contracts.asset; -import kotlin.*; -import net.corda.core.contracts.*; -import net.corda.core.serialization.*; -import org.junit.*; +import kotlin.Unit; +import net.corda.core.contracts.PartyAndReference; +import net.corda.core.identity.AnonymousParty; +import net.corda.core.serialization.OpaqueBytes; +import org.junit.Test; -import static net.corda.core.contracts.ContractsDSL.*; -import static net.corda.core.utilities.TestConstants.*; +import static net.corda.core.contracts.ContractsDSL.DOLLARS; +import static net.corda.core.contracts.ContractsDSL.issuedBy; +import static net.corda.core.utilities.TestConstants.getDUMMY_PUBKEY_1; +import static net.corda.core.utilities.TestConstants.getDUMMY_PUBKEY_2; import static net.corda.testing.CoreTestUtils.*; /** @@ -15,8 +18,8 @@ import static net.corda.testing.CoreTestUtils.*; public class CashTestsJava { private final OpaqueBytes defaultRef = new OpaqueBytes(new byte[]{1}); private final PartyAndReference defaultIssuer = getMEGA_CORP().ref(defaultRef); - private final Cash.State inState = new Cash.State(issuedBy(DOLLARS(1000), defaultIssuer), getDUMMY_PUBKEY_1()); - private final Cash.State outState = new Cash.State(inState.getAmount(), getDUMMY_PUBKEY_2()); + private final Cash.State inState = new Cash.State(issuedBy(DOLLARS(1000), defaultIssuer), new AnonymousParty(getDUMMY_PUBKEY_1())); + private final Cash.State outState = new Cash.State(inState.getAmount(), new AnonymousParty(getDUMMY_PUBKEY_2())); @Test public void trivial() { @@ -26,7 +29,7 @@ public class CashTestsJava { tx.failsWith("the amounts balance"); tx.tweak(tw -> { - tw.output(new Cash.State(issuedBy(DOLLARS(2000), defaultIssuer), getDUMMY_PUBKEY_2())); + tw.output(new Cash.State(issuedBy(DOLLARS(2000), defaultIssuer), new AnonymousParty(getDUMMY_PUBKEY_2()))); return tw.failsWith("the amounts balance"); }); diff --git a/finance/src/test/kotlin/net/corda/contracts/CommercialPaperTests.kt b/finance/src/test/kotlin/net/corda/contracts/CommercialPaperTests.kt index b68aaf0221..11f47d4161 100644 --- a/finance/src/test/kotlin/net/corda/contracts/CommercialPaperTests.kt +++ b/finance/src/test/kotlin/net/corda/contracts/CommercialPaperTests.kt @@ -4,15 +4,13 @@ import net.corda.contracts.asset.* import net.corda.contracts.testing.fillWithSomeTestCash import net.corda.core.contracts.* import net.corda.core.days +import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import net.corda.core.node.services.Vault import net.corda.core.node.services.VaultService import net.corda.core.seconds import net.corda.core.transactions.SignedTransaction -import net.corda.core.utilities.DUMMY_NOTARY -import net.corda.core.utilities.DUMMY_NOTARY_KEY -import net.corda.core.utilities.DUMMY_PUBKEY_1 -import net.corda.core.utilities.TEST_TX_TIME +import net.corda.core.utilities.* import net.corda.node.utilities.configureDatabase import net.corda.node.utilities.transaction import net.corda.testing.* @@ -38,7 +36,7 @@ interface ICommercialPaperTestTemplate { class JavaCommercialPaperTest : ICommercialPaperTestTemplate { override fun getPaper(): ICommercialPaperState = JavaCommercialPaper.State( MEGA_CORP.ref(123), - MEGA_CORP_PUBKEY, + MEGA_CORP, 1000.DOLLARS `issued by` MEGA_CORP.ref(123), TEST_TX_TIME + 7.days ) @@ -51,7 +49,7 @@ class JavaCommercialPaperTest : ICommercialPaperTestTemplate { class KotlinCommercialPaperTest : ICommercialPaperTestTemplate { override fun getPaper(): ICommercialPaperState = CommercialPaper.State( issuance = MEGA_CORP.ref(123), - owner = MEGA_CORP_PUBKEY, + owner = MEGA_CORP, faceValue = 1000.DOLLARS `issued by` MEGA_CORP.ref(123), maturityDate = TEST_TX_TIME + 7.days ) @@ -64,7 +62,7 @@ class KotlinCommercialPaperTest : ICommercialPaperTestTemplate { class KotlinCommercialPaperLegacyTest : ICommercialPaperTestTemplate { override fun getPaper(): ICommercialPaperState = CommercialPaperLegacy.State( issuance = MEGA_CORP.ref(123), - owner = MEGA_CORP_PUBKEY, + owner = MEGA_CORP, faceValue = 1000.DOLLARS `issued by` MEGA_CORP.ref(123), maturityDate = TEST_TX_TIME + 7.days ) @@ -91,8 +89,8 @@ class CommercialPaperTestsGeneric { val someProfits = 1200.DOLLARS `issued by` issuer ledger { unverifiedTransaction { - output("alice's $900", 900.DOLLARS.CASH `issued by` issuer `owned by` ALICE_PUBKEY) - output("some profits", someProfits.STATE `owned by` MEGA_CORP_PUBKEY) + output("alice's $900", 900.DOLLARS.CASH `issued by` issuer `owned by` ALICE) + output("some profits", someProfits.STATE `owned by` MEGA_CORP) } // Some CP is issued onto the ledger by MegaCorp. @@ -108,8 +106,8 @@ class CommercialPaperTestsGeneric { transaction("Trade") { input("paper") input("alice's $900") - output("borrowed $900") { 900.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP_PUBKEY } - output("alice's paper") { "paper".output() `owned by` ALICE_PUBKEY } + output("borrowed $900") { 900.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP } + output("alice's paper") { "paper".output() `owned by` ALICE } command(ALICE_PUBKEY) { Cash.Commands.Move() } command(MEGA_CORP_PUBKEY) { thisTest.getMoveCommand() } this.verifies() @@ -122,8 +120,8 @@ class CommercialPaperTestsGeneric { input("some profits") fun TransactionDSL.outputs(aliceGetsBack: Amount>) { - output("Alice's profit") { aliceGetsBack.STATE `owned by` ALICE_PUBKEY } - output("Change") { (someProfits - aliceGetsBack).STATE `owned by` MEGA_CORP_PUBKEY } + output("Alice's profit") { aliceGetsBack.STATE `owned by` ALICE } + output("Change") { (someProfits - aliceGetsBack).STATE `owned by` MEGA_CORP } } command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() } @@ -270,8 +268,8 @@ class CommercialPaperTestsGeneric { // Alice pays $9000 to BigCorp to own some of their debt. moveTX = run { val ptx = TransactionType.General.Builder(DUMMY_NOTARY) - aliceVaultService.generateSpend(ptx, 9000.DOLLARS, bigCorpServices.key.public) - CommercialPaper().generateMove(ptx, issueTX.tx.outRef(0), aliceServices.key.public) + aliceVaultService.generateSpend(ptx, 9000.DOLLARS, AnonymousParty(bigCorpServices.key.public)) + CommercialPaper().generateMove(ptx, issueTX.tx.outRef(0), AnonymousParty(aliceServices.key.public)) ptx.signWith(bigCorpServices.key) ptx.signWith(aliceServices.key) ptx.signWith(DUMMY_NOTARY_KEY) diff --git a/finance/src/test/kotlin/net/corda/contracts/asset/CashTests.kt b/finance/src/test/kotlin/net/corda/contracts/asset/CashTests.kt index 8bbfd5d5fa..bbb6e1aaf1 100644 --- a/finance/src/test/kotlin/net/corda/contracts/asset/CashTests.kt +++ b/finance/src/test/kotlin/net/corda/contracts/asset/CashTests.kt @@ -2,8 +2,10 @@ package net.corda.contracts.asset import net.corda.contracts.testing.fillWithSomeTestCash import net.corda.core.contracts.* -import net.corda.core.crypto.* +import net.corda.core.crypto.SecureHash +import net.corda.core.crypto.generateKeyPair import net.corda.core.identity.AbstractParty +import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import net.corda.core.node.services.VaultService import net.corda.core.node.services.unconsumedStates @@ -23,7 +25,6 @@ import org.junit.Before import org.junit.Test import java.io.Closeable import java.security.KeyPair -import java.security.PublicKey import java.util.* import kotlin.test.* @@ -32,11 +33,11 @@ class CashTests { val defaultIssuer = MEGA_CORP.ref(defaultRef) val inState = Cash.State( amount = 1000.DOLLARS `issued by` defaultIssuer, - owner = DUMMY_PUBKEY_1 + owner = AnonymousParty(DUMMY_PUBKEY_1) ) // Input state held by the issuer - val issuerInState = inState.copy(owner = defaultIssuer.party.owningKey) - val outState = issuerInState.copy(owner = DUMMY_PUBKEY_2) + val issuerInState = inState.copy(owner = defaultIssuer.party) + val outState = issuerInState.copy(owner = AnonymousParty(DUMMY_PUBKEY_2)) fun Cash.State.editDepositRef(ref: Byte) = copy( amount = Amount(amount.quantity, token = amount.token.copy(amount.token.issuer.copy(reference = OpaqueBytes.of(ref)))) @@ -70,13 +71,13 @@ class CashTests { } services.fillWithSomeTestCash(howMuch = 100.DOLLARS, atLeastThisManyStates = 1, atMostThisManyStates = 1, - issuedBy = MEGA_CORP.ref(1), issuerKey = MEGA_CORP_KEY, ownedBy = OUR_PUBKEY_1) + issuedBy = MEGA_CORP.ref(1), issuerKey = MEGA_CORP_KEY, ownedBy = OUR_IDENTITY_1) services.fillWithSomeTestCash(howMuch = 400.DOLLARS, atLeastThisManyStates = 1, atMostThisManyStates = 1, - issuedBy = MEGA_CORP.ref(1), issuerKey = MEGA_CORP_KEY, ownedBy = OUR_PUBKEY_1) + issuedBy = MEGA_CORP.ref(1), issuerKey = MEGA_CORP_KEY, ownedBy = OUR_IDENTITY_1) services.fillWithSomeTestCash(howMuch = 80.DOLLARS, atLeastThisManyStates = 1, atMostThisManyStates = 1, - issuedBy = MINI_CORP.ref(1), issuerKey = MINI_CORP_KEY, ownedBy = OUR_PUBKEY_1) + issuedBy = MINI_CORP.ref(1), issuerKey = MINI_CORP_KEY, ownedBy = OUR_IDENTITY_1) services.fillWithSomeTestCash(howMuch = 80.SWISS_FRANCS, atLeastThisManyStates = 1, atMostThisManyStates = 1, - issuedBy = MINI_CORP.ref(1), issuerKey = MINI_CORP_KEY, ownedBy = OUR_PUBKEY_1) + issuedBy = MINI_CORP.ref(1), issuerKey = MINI_CORP_KEY, ownedBy = OUR_IDENTITY_1) vaultStatesUnconsumed = services.vaultService.unconsumedStates().toList() } @@ -142,7 +143,7 @@ class CashTests { output { Cash.State( amount = 1000.DOLLARS `issued by` MINI_CORP.ref(12, 34), - owner = DUMMY_PUBKEY_1 + owner = AnonymousParty(DUMMY_PUBKEY_1) ) } tweak { @@ -158,14 +159,14 @@ class CashTests { fun generateIssueRaw() { // Test generation works. val tx: WireTransaction = TransactionType.General.Builder(notary = null).apply { - Cash().generateIssue(this, 100.DOLLARS `issued by` MINI_CORP.ref(12, 34), owner = DUMMY_PUBKEY_1, notary = DUMMY_NOTARY) + Cash().generateIssue(this, 100.DOLLARS `issued by` MINI_CORP.ref(12, 34), owner = AnonymousParty(DUMMY_PUBKEY_1), notary = DUMMY_NOTARY) signWith(MINI_CORP_KEY) }.toSignedTransaction().tx assertTrue(tx.inputs.isEmpty()) val s = tx.outputs[0].data as Cash.State assertEquals(100.DOLLARS `issued by` MINI_CORP.ref(12, 34), s.amount) assertEquals(MINI_CORP as AbstractParty, s.amount.token.issuer.party) - assertEquals(DUMMY_PUBKEY_1, s.owner) + assertEquals(AnonymousParty(DUMMY_PUBKEY_1), s.owner) assertTrue(tx.commands[0].value is Cash.Commands.Issue) assertEquals(MINI_CORP_PUBKEY, tx.commands[0].signers[0]) } @@ -175,7 +176,7 @@ class CashTests { // Test issuance from an issued amount val amount = 100.DOLLARS `issued by` MINI_CORP.ref(12, 34) val tx: WireTransaction = TransactionType.General.Builder(notary = null).apply { - Cash().generateIssue(this, amount, owner = DUMMY_PUBKEY_1, notary = DUMMY_NOTARY) + Cash().generateIssue(this, amount, owner = AnonymousParty(DUMMY_PUBKEY_1), notary = DUMMY_NOTARY) signWith(MINI_CORP_KEY) }.toSignedTransaction().tx assertTrue(tx.inputs.isEmpty()) @@ -248,14 +249,14 @@ class CashTests { // Issue some cash var ptx = TransactionType.General.Builder(DUMMY_NOTARY) - Cash().generateIssue(ptx, 100.DOLLARS `issued by` MINI_CORP.ref(12, 34), owner = MINI_CORP_PUBKEY, notary = DUMMY_NOTARY) + Cash().generateIssue(ptx, 100.DOLLARS `issued by` MINI_CORP.ref(12, 34), owner = MINI_CORP, notary = DUMMY_NOTARY) ptx.signWith(MINI_CORP_KEY) val tx = ptx.toSignedTransaction() // Include the previously issued cash in a new issuance command ptx = TransactionType.General.Builder(DUMMY_NOTARY) ptx.addInputState(tx.tx.outRef(0)) - Cash().generateIssue(ptx, 100.DOLLARS `issued by` MINI_CORP.ref(12, 34), owner = MINI_CORP_PUBKEY, notary = DUMMY_NOTARY) + Cash().generateIssue(ptx, 100.DOLLARS `issued by` MINI_CORP.ref(12, 34), owner = MINI_CORP, notary = DUMMY_NOTARY) } @Test @@ -329,7 +330,7 @@ class CashTests { input { inState.copy( amount = 150.POUNDS `issued by` defaultIssuer, - owner = DUMMY_PUBKEY_2 + owner = AnonymousParty(DUMMY_PUBKEY_2) ) } output { outState.copy(amount = 1150.DOLLARS `issued by` defaultIssuer) } @@ -382,10 +383,10 @@ class CashTests { // Multi-issuer case. transaction { input { issuerInState } - input { issuerInState.copy(owner = MINI_CORP_PUBKEY) `issued by` MINI_CORP } + input { issuerInState.copy(owner = MINI_CORP) `issued by` MINI_CORP } output { issuerInState.copy(amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer)) `issued by` MINI_CORP } - output { issuerInState.copy(owner = MINI_CORP_PUBKEY, amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer)) } + output { issuerInState.copy(owner = MINI_CORP, amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer)) } command(MEGA_CORP_PUBKEY, MINI_CORP_PUBKEY) { Cash.Commands.Move() } @@ -420,19 +421,19 @@ class CashTests { // Can't merge them together. tweak { - output { inState.copy(owner = DUMMY_PUBKEY_2, amount = 2000.DOLLARS `issued by` defaultIssuer) } + output { inState.copy(owner = AnonymousParty(DUMMY_PUBKEY_2), amount = 2000.DOLLARS `issued by` defaultIssuer) } this `fails with` "the amounts balance" } // Missing MiniCorp deposit tweak { - output { inState.copy(owner = DUMMY_PUBKEY_2) } - output { inState.copy(owner = DUMMY_PUBKEY_2) } + output { inState.copy(owner = AnonymousParty(DUMMY_PUBKEY_2)) } + output { inState.copy(owner = AnonymousParty(DUMMY_PUBKEY_2)) } this `fails with` "the amounts balance" } // This works. - output { inState.copy(owner = DUMMY_PUBKEY_2) } - output { inState.copy(owner = DUMMY_PUBKEY_2) `issued by` MINI_CORP } + output { inState.copy(owner = AnonymousParty(DUMMY_PUBKEY_2)) } + output { inState.copy(owner = AnonymousParty(DUMMY_PUBKEY_2)) `issued by` MINI_CORP } command(DUMMY_PUBKEY_1) { Cash.Commands.Move() } this.verifies() } @@ -442,11 +443,11 @@ class CashTests { fun multiCurrency() { // Check we can do an atomic currency trade tx. transaction { - val pounds = Cash.State(658.POUNDS `issued by` MINI_CORP.ref(3, 4, 5), DUMMY_PUBKEY_2) - input { inState `owned by` DUMMY_PUBKEY_1 } + val pounds = Cash.State(658.POUNDS `issued by` MINI_CORP.ref(3, 4, 5), AnonymousParty(DUMMY_PUBKEY_2)) + input { inState `owned by` AnonymousParty(DUMMY_PUBKEY_1) } input { pounds } - output { inState `owned by` DUMMY_PUBKEY_2 } - output { pounds `owned by` DUMMY_PUBKEY_1 } + output { inState `owned by` AnonymousParty(DUMMY_PUBKEY_2) } + output { pounds `owned by` AnonymousParty(DUMMY_PUBKEY_1) } command(DUMMY_PUBKEY_1, DUMMY_PUBKEY_2) { Cash.Commands.Move() } this.verifies() @@ -458,13 +459,13 @@ class CashTests { // Spend tx generation val OUR_KEY: KeyPair by lazy { generateKeyPair() } - val OUR_PUBKEY_1: PublicKey get() = OUR_KEY.public + val OUR_IDENTITY_1: AbstractParty get() = AnonymousParty(OUR_KEY.public) - val THEIR_PUBKEY_1 = DUMMY_PUBKEY_2 + val THEIR_IDENTITY_1 = AnonymousParty(DUMMY_PUBKEY_2) fun makeCash(amount: Amount, corp: Party, depositRef: Byte = 1) = StateAndRef( - Cash.State(amount `issued by` corp.ref(depositRef), OUR_PUBKEY_1) `with notary` DUMMY_NOTARY, + Cash.State(amount `issued by` corp.ref(depositRef), OUR_IDENTITY_1) `with notary` DUMMY_NOTARY, StateRef(SecureHash.randomSHA256(), Random().nextInt(32)) ) @@ -484,7 +485,7 @@ class CashTests { return tx.toWireTransaction() } - fun makeSpend(amount: Amount, dest: PublicKey): WireTransaction { + fun makeSpend(amount: Amount, dest: AbstractParty): WireTransaction { val tx = TransactionType.General.Builder(DUMMY_NOTARY) database.transaction { vault.generateSpend(tx, amount, dest) @@ -566,13 +567,13 @@ class CashTests { database.transaction { - val wtx = makeSpend(100.DOLLARS, THEIR_PUBKEY_1) + val wtx = makeSpend(100.DOLLARS, THEIR_IDENTITY_1) @Suppress("UNCHECKED_CAST") val vaultState = vaultStatesUnconsumed.elementAt(0) assertEquals(vaultState.ref, wtx.inputs[0]) - assertEquals(vaultState.state.data.copy(owner = THEIR_PUBKEY_1), wtx.outputs[0].data) - assertEquals(OUR_PUBKEY_1, wtx.commands.single { it.value is Cash.Commands.Move }.signers[0]) + assertEquals(vaultState.state.data.copy(owner = THEIR_IDENTITY_1), wtx.outputs[0].data) + assertEquals(OUR_IDENTITY_1.owningKey, wtx.commands.single { it.value is Cash.Commands.Move }.signers[0]) } } @@ -582,7 +583,7 @@ class CashTests { database.transaction { val tx = TransactionType.General.Builder(DUMMY_NOTARY) - vault.generateSpend(tx, 80.DOLLARS, ALICE_PUBKEY, setOf(MINI_CORP.toAnonymous())) + vault.generateSpend(tx, 80.DOLLARS, ALICE, setOf(MINI_CORP)) assertEquals(vaultStatesUnconsumed.elementAt(2).ref, tx.inputStates()[0]) } @@ -593,14 +594,14 @@ class CashTests { database.transaction { - val wtx = makeSpend(10.DOLLARS, THEIR_PUBKEY_1) + val wtx = makeSpend(10.DOLLARS, THEIR_IDENTITY_1) @Suppress("UNCHECKED_CAST") val vaultState = vaultStatesUnconsumed.elementAt(0) assertEquals(vaultState.ref, wtx.inputs[0]) - assertEquals(vaultState.state.data.copy(owner = THEIR_PUBKEY_1, amount = 10.DOLLARS `issued by` defaultIssuer), wtx.outputs[0].data) + assertEquals(vaultState.state.data.copy(owner = THEIR_IDENTITY_1, amount = 10.DOLLARS `issued by` defaultIssuer), wtx.outputs[0].data) assertEquals(vaultState.state.data.copy(amount = 90.DOLLARS `issued by` defaultIssuer), wtx.outputs[1].data) - assertEquals(OUR_PUBKEY_1, wtx.commands.single { it.value is Cash.Commands.Move }.signers[0]) + assertEquals(OUR_IDENTITY_1.owningKey, wtx.commands.single { it.value is Cash.Commands.Move }.signers[0]) } } @@ -608,15 +609,15 @@ class CashTests { fun generateSpendWithTwoInputs() { database.transaction { - val wtx = makeSpend(500.DOLLARS, THEIR_PUBKEY_1) + val wtx = makeSpend(500.DOLLARS, THEIR_IDENTITY_1) @Suppress("UNCHECKED_CAST") val vaultState0 = vaultStatesUnconsumed.elementAt(0) val vaultState1 = vaultStatesUnconsumed.elementAt(1) assertEquals(vaultState0.ref, wtx.inputs[0]) assertEquals(vaultState1.ref, wtx.inputs[1]) - assertEquals(vaultState0.state.data.copy(owner = THEIR_PUBKEY_1, amount = 500.DOLLARS `issued by` defaultIssuer), wtx.outputs[0].data) - assertEquals(OUR_PUBKEY_1, wtx.commands.single { it.value is Cash.Commands.Move }.signers[0]) + assertEquals(vaultState0.state.data.copy(owner = THEIR_IDENTITY_1, amount = 500.DOLLARS `issued by` defaultIssuer), wtx.outputs[0].data) + assertEquals(OUR_IDENTITY_1.owningKey, wtx.commands.single { it.value is Cash.Commands.Move }.signers[0]) } } @@ -624,7 +625,7 @@ class CashTests { fun generateSpendMixedDeposits() { database.transaction { - val wtx = makeSpend(580.DOLLARS, THEIR_PUBKEY_1) + val wtx = makeSpend(580.DOLLARS, THEIR_IDENTITY_1) assertEquals(3, wtx.inputs.size) @Suppress("UNCHECKED_CAST") @@ -635,9 +636,9 @@ class CashTests { assertEquals(vaultState0.ref, wtx.inputs[0]) assertEquals(vaultState1.ref, wtx.inputs[1]) assertEquals(vaultState2.ref, wtx.inputs[2]) - assertEquals(vaultState0.state.data.copy(owner = THEIR_PUBKEY_1, amount = 500.DOLLARS `issued by` defaultIssuer), wtx.outputs[1].data) - assertEquals(vaultState2.state.data.copy(owner = THEIR_PUBKEY_1), wtx.outputs[0].data) - assertEquals(OUR_PUBKEY_1, wtx.commands.single { it.value is Cash.Commands.Move }.signers[0]) + assertEquals(vaultState0.state.data.copy(owner = THEIR_IDENTITY_1, amount = 500.DOLLARS `issued by` defaultIssuer), wtx.outputs[1].data) + assertEquals(vaultState2.state.data.copy(owner = THEIR_IDENTITY_1), wtx.outputs[0].data) + assertEquals(OUR_IDENTITY_1.owningKey, wtx.commands.single { it.value is Cash.Commands.Move }.signers[0]) } } @@ -647,12 +648,12 @@ class CashTests { database.transaction { val e: InsufficientBalanceException = assertFailsWith("balance") { - makeSpend(1000.DOLLARS, THEIR_PUBKEY_1) + makeSpend(1000.DOLLARS, THEIR_IDENTITY_1) } assertEquals((1000 - 580).DOLLARS, e.amountMissing) assertFailsWith(InsufficientBalanceException::class) { - makeSpend(81.SWISS_FRANCS, THEIR_PUBKEY_1) + makeSpend(81.SWISS_FRANCS, THEIR_IDENTITY_1) } } } @@ -662,9 +663,9 @@ class CashTests { */ @Test fun aggregation() { - val fiveThousandDollarsFromMega = Cash.State(5000.DOLLARS `issued by` MEGA_CORP.ref(2), MEGA_CORP_PUBKEY) - val twoThousandDollarsFromMega = Cash.State(2000.DOLLARS `issued by` MEGA_CORP.ref(2), MINI_CORP_PUBKEY) - val oneThousandDollarsFromMini = Cash.State(1000.DOLLARS `issued by` MINI_CORP.ref(3), MEGA_CORP_PUBKEY) + val fiveThousandDollarsFromMega = Cash.State(5000.DOLLARS `issued by` MEGA_CORP.ref(2), MEGA_CORP) + val twoThousandDollarsFromMega = Cash.State(2000.DOLLARS `issued by` MEGA_CORP.ref(2), MINI_CORP) + val oneThousandDollarsFromMini = Cash.State(1000.DOLLARS `issued by` MINI_CORP.ref(3), MEGA_CORP) // Obviously it must be possible to aggregate states with themselves assertEquals(fiveThousandDollarsFromMega.amount.token, fiveThousandDollarsFromMega.amount.token) @@ -678,7 +679,7 @@ class CashTests { // States cannot be aggregated if the currency differs assertNotEquals(oneThousandDollarsFromMini.amount.token, - Cash.State(1000.POUNDS `issued by` MINI_CORP.ref(3), MEGA_CORP_PUBKEY).amount.token) + Cash.State(1000.POUNDS `issued by` MINI_CORP.ref(3), MEGA_CORP).amount.token) // States cannot be aggregated if the reference differs assertNotEquals(fiveThousandDollarsFromMega.amount.token, (fiveThousandDollarsFromMega `with deposit` defaultIssuer).amount.token) @@ -688,20 +689,20 @@ class CashTests { @Test fun `summing by owner`() { val states = listOf( - Cash.State(1000.DOLLARS `issued by` defaultIssuer, MINI_CORP_PUBKEY), - Cash.State(2000.DOLLARS `issued by` defaultIssuer, MEGA_CORP_PUBKEY), - Cash.State(4000.DOLLARS `issued by` defaultIssuer, MEGA_CORP_PUBKEY) + Cash.State(1000.DOLLARS `issued by` defaultIssuer, MINI_CORP), + Cash.State(2000.DOLLARS `issued by` defaultIssuer, MEGA_CORP), + Cash.State(4000.DOLLARS `issued by` defaultIssuer, MEGA_CORP) ) - assertEquals(6000.DOLLARS `issued by` defaultIssuer, states.sumCashBy(MEGA_CORP_PUBKEY)) + assertEquals(6000.DOLLARS `issued by` defaultIssuer, states.sumCashBy(MEGA_CORP)) } @Test(expected = UnsupportedOperationException::class) fun `summing by owner throws`() { val states = listOf( - Cash.State(2000.DOLLARS `issued by` defaultIssuer, MEGA_CORP_PUBKEY), - Cash.State(4000.DOLLARS `issued by` defaultIssuer, MEGA_CORP_PUBKEY) + Cash.State(2000.DOLLARS `issued by` defaultIssuer, MEGA_CORP), + Cash.State(4000.DOLLARS `issued by` defaultIssuer, MEGA_CORP) ) - states.sumCashBy(MINI_CORP_PUBKEY) + states.sumCashBy(MINI_CORP) } @Test @@ -720,9 +721,9 @@ class CashTests { @Test fun `summing a single currency`() { val states = listOf( - Cash.State(1000.DOLLARS `issued by` defaultIssuer, MEGA_CORP_PUBKEY), - Cash.State(2000.DOLLARS `issued by` defaultIssuer, MEGA_CORP_PUBKEY), - Cash.State(4000.DOLLARS `issued by` defaultIssuer, MEGA_CORP_PUBKEY) + Cash.State(1000.DOLLARS `issued by` defaultIssuer, MEGA_CORP), + Cash.State(2000.DOLLARS `issued by` defaultIssuer, MEGA_CORP), + Cash.State(4000.DOLLARS `issued by` defaultIssuer, MEGA_CORP) ) // Test that summing everything produces the total number of dollars val expected = 7000.DOLLARS `issued by` defaultIssuer @@ -733,8 +734,8 @@ class CashTests { @Test(expected = IllegalArgumentException::class) fun `summing multiple currencies`() { val states = listOf( - Cash.State(1000.DOLLARS `issued by` defaultIssuer, MEGA_CORP_PUBKEY), - Cash.State(4000.POUNDS `issued by` defaultIssuer, MEGA_CORP_PUBKEY) + Cash.State(1000.DOLLARS `issued by` defaultIssuer, MEGA_CORP), + Cash.State(4000.POUNDS `issued by` defaultIssuer, MEGA_CORP) ) // Test that summing everything fails because we're mixing units states.sumCash() @@ -748,14 +749,14 @@ class CashTests { output("MEGA_CORP cash") { Cash.State( amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1), - owner = MEGA_CORP_PUBKEY + owner = MEGA_CORP ) } } transaction { input("MEGA_CORP cash") - output("MEGA_CORP cash".output().copy(owner = DUMMY_PUBKEY_1)) + output("MEGA_CORP cash".output().copy(owner = AnonymousParty(DUMMY_PUBKEY_1))) command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() } this.verifies() } @@ -764,7 +765,7 @@ class CashTests { transaction { input("MEGA_CORP cash") // We send it to another pubkey so that the transaction is not identical to the previous one - output("MEGA_CORP cash".output().copy(owner = ALICE_PUBKEY)) + output("MEGA_CORP cash".output().copy(owner = ALICE)) command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() } this.verifies() } diff --git a/finance/src/test/kotlin/net/corda/contracts/asset/ObligationTests.kt b/finance/src/test/kotlin/net/corda/contracts/asset/ObligationTests.kt index 2c451a085a..c0333a2c26 100644 --- a/finance/src/test/kotlin/net/corda/contracts/asset/ObligationTests.kt +++ b/finance/src/test/kotlin/net/corda/contracts/asset/ObligationTests.kt @@ -2,13 +2,14 @@ package net.corda.contracts.asset import net.corda.contracts.asset.Obligation.Lifecycle import net.corda.core.contracts.* -import net.corda.core.crypto.NullPublicKey +import net.corda.core.crypto.NULL_PARTY import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty +import net.corda.core.identity.AnonymousParty import net.corda.core.serialization.OpaqueBytes import net.corda.core.utilities.* import net.corda.testing.* import org.junit.Test -import java.security.PublicKey import java.time.Duration import java.time.temporal.ChronoUnit import java.util.* @@ -33,18 +34,18 @@ class ObligationTests { obligor = MEGA_CORP, template = megaCorpDollarSettlement, quantity = 1000.DOLLARS.quantity, - beneficiary = DUMMY_PUBKEY_1 + beneficiary = CHARLIE ) - val outState = inState.copy(beneficiary = DUMMY_PUBKEY_2) + val outState = inState.copy(beneficiary = AnonymousParty(DUMMY_PUBKEY_2)) private fun cashObligationTestRoots( group: LedgerDSL ) = group.apply { unverifiedTransaction { - output("Alice's $1,000,000 obligation to Bob", oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY)) - output("Bob's $1,000,000 obligation to Alice", oneMillionDollars.OBLIGATION between Pair(BOB, ALICE_PUBKEY)) - output("MegaCorp's $1,000,000 obligation to Bob", oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, BOB_PUBKEY)) - output("Alice's $1,000,000", 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE_PUBKEY) + output("Alice's $1,000,000 obligation to Bob", oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)) + output("Bob's $1,000,000 obligation to Alice", oneMillionDollars.OBLIGATION between Pair(BOB, ALICE)) + output("MegaCorp's $1,000,000 obligation to Bob", oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, BOB)) + output("Alice's $1,000,000", 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE) } } @@ -71,13 +72,13 @@ class ObligationTests { tweak { output { outState } output { outState `issued by` MINI_CORP } - command(DUMMY_PUBKEY_1) { Obligation.Commands.Move() } + command(CHARLIE.owningKey) { Obligation.Commands.Move() } this `fails with` "at least one asset input" } // Simple reallocation works. tweak { output { outState } - command(DUMMY_PUBKEY_1) { Obligation.Commands.Move() } + command(CHARLIE.owningKey) { Obligation.Commands.Move() } this.verifies() } } @@ -98,7 +99,7 @@ class ObligationTests { // institution is allowed to issue as much cash as they want. transaction { output { outState } - command(DUMMY_PUBKEY_1) { Obligation.Commands.Issue() } + command(CHARLIE.owningKey) { Obligation.Commands.Issue() } this `fails with` "output states are issued by a command signer" } transaction { @@ -106,7 +107,7 @@ class ObligationTests { Obligation.State( obligor = MINI_CORP, quantity = 1000.DOLLARS.quantity, - beneficiary = DUMMY_PUBKEY_1, + beneficiary = CHARLIE, template = megaCorpDollarSettlement ) } @@ -121,14 +122,14 @@ class ObligationTests { // Test generation works. val tx = TransactionType.General.Builder(notary = null).apply { Obligation().generateIssue(this, MINI_CORP, megaCorpDollarSettlement, 100.DOLLARS.quantity, - beneficiary = DUMMY_PUBKEY_1, notary = DUMMY_NOTARY) + beneficiary = CHARLIE, notary = DUMMY_NOTARY) signWith(MINI_CORP_KEY) }.toSignedTransaction().tx assertTrue(tx.inputs.isEmpty()) val expected = Obligation.State( obligor = MINI_CORP, quantity = 100.DOLLARS.quantity, - beneficiary = DUMMY_PUBKEY_1, + beneficiary = CHARLIE, template = megaCorpDollarSettlement ) assertEquals(tx.outputs[0].data, expected) @@ -142,7 +143,7 @@ class ObligationTests { // Move fails: not allowed to summon money. tweak { - command(DUMMY_PUBKEY_1) { Obligation.Commands.Move() } + command(CHARLIE.owningKey) { Obligation.Commands.Move() } this `fails with` "the amounts balance" } @@ -199,7 +200,7 @@ class ObligationTests { // Issue some obligation val tx = TransactionType.General.Builder(DUMMY_NOTARY).apply { Obligation().generateIssue(this, MINI_CORP, megaCorpDollarSettlement, 100.DOLLARS.quantity, - beneficiary = MINI_CORP_PUBKEY, notary = DUMMY_NOTARY) + beneficiary = MINI_CORP, notary = DUMMY_NOTARY) signWith(MINI_CORP_KEY) }.toSignedTransaction() @@ -207,16 +208,16 @@ class ObligationTests { val ptx = TransactionType.General.Builder(DUMMY_NOTARY) ptx.addInputState(tx.tx.outRef>(0)) Obligation().generateIssue(ptx, MINI_CORP, megaCorpDollarSettlement, 100.DOLLARS.quantity, - beneficiary = MINI_CORP_PUBKEY, notary = DUMMY_NOTARY) + beneficiary = MINI_CORP, notary = DUMMY_NOTARY) } /** Test generating a transaction to net two obligations of the same size, and therefore there are no outputs. */ @Test fun `generate close-out net transaction`() { - val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY) - val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE_PUBKEY) + val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) + val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE) val tx = TransactionType.General.Builder(DUMMY_NOTARY).apply { - Obligation().generateCloseOutNetting(this, ALICE_PUBKEY, obligationAliceToBob, obligationBobToAlice) + Obligation().generateCloseOutNetting(this, ALICE, obligationAliceToBob, obligationBobToAlice) signWith(ALICE_KEY) signWith(DUMMY_NOTARY_KEY) }.toSignedTransaction().tx @@ -226,24 +227,24 @@ class ObligationTests { /** Test generating a transaction to net two obligations of the different sizes, and confirm the balance is correct. */ @Test fun `generate close-out net transaction with remainder`() { - val obligationAliceToBob = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(ALICE, BOB_PUBKEY) - val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE_PUBKEY) + val obligationAliceToBob = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(ALICE, BOB) + val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE) val tx = TransactionType.General.Builder(DUMMY_NOTARY).apply { - Obligation().generateCloseOutNetting(this, ALICE_PUBKEY, obligationAliceToBob, obligationBobToAlice) + Obligation().generateCloseOutNetting(this, ALICE, obligationAliceToBob, obligationBobToAlice) signWith(ALICE_KEY) signWith(DUMMY_NOTARY_KEY) }.toSignedTransaction().tx assertEquals(1, tx.outputs.size) val actual = tx.outputs[0].data - assertEquals((1000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(ALICE, BOB_PUBKEY), actual) + assertEquals((1000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(ALICE, BOB), actual) } /** Test generating a transaction to net two obligations of the same size, and therefore there are no outputs. */ @Test fun `generate payment net transaction`() { - val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY) - val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE_PUBKEY) + val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) + val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE) val tx = TransactionType.General.Builder(DUMMY_NOTARY).apply { Obligation().generatePaymentNetting(this, obligationAliceToBob.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice) signWith(ALICE_KEY) @@ -256,8 +257,8 @@ class ObligationTests { /** Test generating a transaction to two obligations, where one is bigger than the other and therefore there is a remainder. */ @Test fun `generate payment net transaction with remainder`() { - val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY) - val obligationBobToAlice = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(BOB, ALICE_PUBKEY) + val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) + val obligationBobToAlice = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(BOB, ALICE) val tx = TransactionType.General.Builder(null).apply { Obligation().generatePaymentNetting(this, obligationAliceToBob.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice) signWith(ALICE_KEY) @@ -278,7 +279,7 @@ class ObligationTests { // Generate a transaction issuing the obligation var tx = TransactionType.General.Builder(null).apply { Obligation().generateIssue(this, MINI_CORP, megaCorpDollarSettlement.copy(dueBefore = dueBefore), 100.DOLLARS.quantity, - beneficiary = MINI_CORP_PUBKEY, notary = DUMMY_NOTARY) + beneficiary = MINI_CORP, notary = DUMMY_NOTARY) signWith(MINI_CORP_KEY) }.toSignedTransaction() var stateAndRef = tx.tx.outRef>(0) @@ -309,14 +310,14 @@ class ObligationTests { @Test fun `generate settlement transaction`() { val cashTx = TransactionType.General.Builder(null).apply { - Cash().generateIssue(this, 100.DOLLARS `issued by` defaultIssuer, MINI_CORP_PUBKEY, DUMMY_NOTARY) + Cash().generateIssue(this, 100.DOLLARS `issued by` defaultIssuer, MINI_CORP, DUMMY_NOTARY) signWith(MEGA_CORP_KEY) }.toSignedTransaction().tx // Generate a transaction issuing the obligation val obligationTx = TransactionType.General.Builder(null).apply { Obligation().generateIssue(this, MINI_CORP, megaCorpDollarSettlement, 100.DOLLARS.quantity, - beneficiary = MINI_CORP_PUBKEY, notary = DUMMY_NOTARY) + beneficiary = MINI_CORP, notary = DUMMY_NOTARY) signWith(MINI_CORP_KEY) }.toSignedTransaction().tx @@ -354,7 +355,7 @@ class ObligationTests { input("Alice's $1,000,000 obligation to Bob") input("Bob's $1,000,000 obligation to Alice") input("MegaCorp's $1,000,000 obligation to Bob") - output("change") { oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, BOB_PUBKEY) } + output("change") { oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, BOB) } command(BOB_PUBKEY, MEGA_CORP_PUBKEY) { Obligation.Commands.Net(NetType.CLOSE_OUT) } timestamp(TEST_TX_TIME) this.verifies() @@ -368,7 +369,7 @@ class ObligationTests { transaction("Issuance") { input("Alice's $1,000,000 obligation to Bob") input("Bob's $1,000,000 obligation to Alice") - output("change") { (oneMillionDollars.splitEvenly(2).first()).OBLIGATION between Pair(ALICE, BOB_PUBKEY) } + output("change") { (oneMillionDollars.splitEvenly(2).first()).OBLIGATION between Pair(ALICE, BOB) } command(BOB_PUBKEY) { Obligation.Commands.Net(NetType.CLOSE_OUT) } timestamp(TEST_TX_TIME) this `fails with` "amounts owed on input and output must match" @@ -422,7 +423,7 @@ class ObligationTests { transaction("Issuance") { input("Bob's $1,000,000 obligation to Alice") input("MegaCorp's $1,000,000 obligation to Bob") - output("MegaCorp's $1,000,000 obligation to Alice") { oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, ALICE_PUBKEY) } + output("MegaCorp's $1,000,000 obligation to Alice") { oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, ALICE) } command(ALICE_PUBKEY, BOB_PUBKEY, MEGA_CORP_PUBKEY) { Obligation.Commands.Net(NetType.PAYMENT) } timestamp(TEST_TX_TIME) this.verifies() @@ -436,7 +437,7 @@ class ObligationTests { transaction("Issuance") { input("Bob's $1,000,000 obligation to Alice") input("MegaCorp's $1,000,000 obligation to Bob") - output("MegaCorp's $1,000,000 obligation to Alice") { oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, ALICE_PUBKEY) } + output("MegaCorp's $1,000,000 obligation to Alice") { oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, ALICE) } command(ALICE_PUBKEY, BOB_PUBKEY) { Obligation.Commands.Net(NetType.PAYMENT) } timestamp(TEST_TX_TIME) this `fails with` "all involved parties have signed" @@ -452,7 +453,7 @@ class ObligationTests { transaction("Settlement") { input("Alice's $1,000,000 obligation to Bob") input("Alice's $1,000,000") - output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY } + output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB } command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity, inState.amount.token)) } command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation().legalContractReference) } this.verifies() @@ -463,10 +464,10 @@ class ObligationTests { val halfAMillionDollars = 500000.DOLLARS `issued by` defaultIssuer ledger { transaction("Settlement") { - input(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY)) - input(500000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE_PUBKEY) - output("Alice's $500,000 obligation to Bob") { halfAMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY) } - output("Bob's $500,000") { 500000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY } + input(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)) + input(500000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE) + output("Alice's $500,000 obligation to Bob") { halfAMillionDollars.OBLIGATION between Pair(ALICE, BOB) } + output("Bob's $500,000") { 500000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB } command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity / 2, inState.amount.token)) } command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation().legalContractReference) } this.verifies() @@ -474,12 +475,12 @@ class ObligationTests { } // Make sure we can't settle an obligation that's defaulted - val defaultedObligation: Obligation.State = (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY)).copy(lifecycle = Lifecycle.DEFAULTED) + val defaultedObligation: Obligation.State = (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)).copy(lifecycle = Lifecycle.DEFAULTED) ledger { transaction("Settlement") { input(defaultedObligation) // Alice's defaulted $1,000,000 obligation to Bob - input(1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE_PUBKEY) - output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY } + input(1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE) + output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB } command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity, inState.amount.token)) } command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation().legalContractReference) } this `fails with` "all inputs are in the normal state" @@ -492,7 +493,7 @@ class ObligationTests { transaction("Settlement") { input("Alice's $1,000,000 obligation to Bob") input("Alice's $1,000,000") - output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY } + output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB } command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity / 2, inState.amount.token)) } command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation().legalContractReference) } this `fails with` "amount in settle command" @@ -506,17 +507,17 @@ class ObligationTests { val oneUnitFcoj = Amount(1, defaultFcoj) val obligationDef = Obligation.Terms(nonEmptySetOf(CommodityContract().legalContractReference), nonEmptySetOf(defaultFcoj), TEST_TX_TIME) val oneUnitFcojObligation = Obligation.State(Obligation.Lifecycle.NORMAL, ALICE, - obligationDef, oneUnitFcoj.quantity, NullPublicKey) + obligationDef, oneUnitFcoj.quantity, NULL_PARTY) // Try settling a simple commodity obligation ledger { unverifiedTransaction { - output("Alice's 1 FCOJ obligation to Bob", oneUnitFcojObligation between Pair(ALICE, BOB_PUBKEY)) - output("Alice's 1 FCOJ", CommodityContract.State(oneUnitFcoj, ALICE_PUBKEY)) + output("Alice's 1 FCOJ obligation to Bob", oneUnitFcojObligation between Pair(ALICE, BOB)) + output("Alice's 1 FCOJ", CommodityContract.State(oneUnitFcoj, ALICE)) } transaction("Settlement") { input("Alice's 1 FCOJ obligation to Bob") input("Alice's 1 FCOJ") - output("Bob's 1 FCOJ") { CommodityContract.State(oneUnitFcoj, BOB_PUBKEY) } + output("Bob's 1 FCOJ") { CommodityContract.State(oneUnitFcoj, BOB) } command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneUnitFcoj.quantity, oneUnitFcojObligation.amount.token)) } command(ALICE_PUBKEY) { CommodityContract.Commands.Move(Obligation().legalContractReference) } verifies() @@ -531,7 +532,7 @@ class ObligationTests { cashObligationTestRoots(this) transaction("Settlement") { input("Alice's $1,000,000 obligation to Bob") - output("Alice's defaulted $1,000,000 obligation to Bob") { (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY)).copy(lifecycle = Lifecycle.DEFAULTED) } + output("Alice's defaulted $1,000,000 obligation to Bob") { (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)).copy(lifecycle = Lifecycle.DEFAULTED) } command(BOB_PUBKEY) { Obligation.Commands.SetLifecycle(Lifecycle.DEFAULTED) } this `fails with` "there is a timestamp from the authority" } @@ -541,8 +542,8 @@ class ObligationTests { val pastTestTime = TEST_TX_TIME - Duration.ofDays(7) val futureTestTime = TEST_TX_TIME + Duration.ofDays(7) transaction("Settlement") { - input(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY) `at` futureTestTime) - output("Alice's defaulted $1,000,000 obligation to Bob") { (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY) `at` futureTestTime).copy(lifecycle = Lifecycle.DEFAULTED) } + input(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` futureTestTime) + output("Alice's defaulted $1,000,000 obligation to Bob") { (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` futureTestTime).copy(lifecycle = Lifecycle.DEFAULTED) } command(BOB_PUBKEY) { Obligation.Commands.SetLifecycle(Lifecycle.DEFAULTED) } timestamp(TEST_TX_TIME) this `fails with` "the due date has passed" @@ -551,8 +552,8 @@ class ObligationTests { // Try defaulting an obligation that is now in the past ledger { transaction("Settlement") { - input(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY) `at` pastTestTime) - output("Alice's defaulted $1,000,000 obligation to Bob") { (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY) `at` pastTestTime).copy(lifecycle = Lifecycle.DEFAULTED) } + input(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` pastTestTime) + output("Alice's defaulted $1,000,000 obligation to Bob") { (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` pastTestTime).copy(lifecycle = Lifecycle.DEFAULTED) } command(BOB_PUBKEY) { Obligation.Commands.SetLifecycle(Lifecycle.DEFAULTED) } timestamp(TEST_TX_TIME) this.verifies() @@ -565,7 +566,7 @@ class ObligationTests { fun testMergeSplit() { // Splitting value works. transaction { - command(DUMMY_PUBKEY_1) { Obligation.Commands.Move() } + command(CHARLIE.owningKey) { Obligation.Commands.Move() } tweak { input { inState } repeat(4) { output { inState.copy(quantity = inState.quantity / 4) } } @@ -624,7 +625,7 @@ class ObligationTests { inState.copy( quantity = 15000, template = megaCorpPoundSettlement, - beneficiary = DUMMY_PUBKEY_2 + beneficiary = AnonymousParty(DUMMY_PUBKEY_2) ) } output { outState.copy(quantity = 115000) } @@ -635,7 +636,7 @@ class ObligationTests { input { inState } input { inState `issued by` MINI_CORP } output { outState } - command(DUMMY_PUBKEY_1) { Obligation.Commands.Move() } + command(CHARLIE.owningKey) { Obligation.Commands.Move() } this `fails with` "the amounts balance" } } @@ -648,17 +649,17 @@ class ObligationTests { output { outState.copy(quantity = inState.quantity - 200.DOLLARS.quantity) } tweak { - command(DUMMY_PUBKEY_1) { Obligation.Commands.Exit(Amount(100.DOLLARS.quantity, inState.amount.token)) } - command(DUMMY_PUBKEY_1) { Obligation.Commands.Move() } + command(CHARLIE.owningKey) { Obligation.Commands.Exit(Amount(100.DOLLARS.quantity, inState.amount.token)) } + command(CHARLIE.owningKey) { Obligation.Commands.Move() } this `fails with` "the amounts balance" } tweak { - command(DUMMY_PUBKEY_1) { Obligation.Commands.Exit(Amount(200.DOLLARS.quantity, inState.amount.token)) } + command(CHARLIE.owningKey) { Obligation.Commands.Exit(Amount(200.DOLLARS.quantity, inState.amount.token)) } this `fails with` "required net.corda.core.contracts.FungibleAsset.Commands.Move command" tweak { - command(DUMMY_PUBKEY_1) { Obligation.Commands.Move() } + command(CHARLIE.owningKey) { Obligation.Commands.Move() } this.verifies() } } @@ -676,14 +677,14 @@ class ObligationTests { output { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedPounds), quantity = inState.quantity - 200.POUNDS.quantity) } output { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedDollars), quantity = inState.quantity - 200.DOLLARS.quantity) } - command(DUMMY_PUBKEY_1) { Obligation.Commands.Move() } + command(CHARLIE.owningKey) { Obligation.Commands.Move() } this `fails with` "the amounts balance" - command(DUMMY_PUBKEY_1) { Obligation.Commands.Exit(Amount(200.DOLLARS.quantity, inState.amount.token.copy(product = megaCorpDollarSettlement))) } + command(CHARLIE.owningKey) { Obligation.Commands.Exit(Amount(200.DOLLARS.quantity, inState.amount.token.copy(product = megaCorpDollarSettlement))) } this `fails with` "the amounts balance" - command(DUMMY_PUBKEY_1) { Obligation.Commands.Exit(Amount(200.POUNDS.quantity, inState.amount.token.copy(product = megaCorpPoundSettlement))) } + command(CHARLIE.owningKey) { Obligation.Commands.Exit(Amount(200.POUNDS.quantity, inState.amount.token.copy(product = megaCorpPoundSettlement))) } this.verifies() } } @@ -697,20 +698,20 @@ class ObligationTests { // Can't merge them together. tweak { - output { inState.copy(beneficiary = DUMMY_PUBKEY_2, quantity = 200000L) } + output { inState.copy(beneficiary = AnonymousParty(DUMMY_PUBKEY_2), quantity = 200000L) } this `fails with` "the amounts balance" } // Missing MiniCorp deposit tweak { - output { inState.copy(beneficiary = DUMMY_PUBKEY_2) } - output { inState.copy(beneficiary = DUMMY_PUBKEY_2) } + output { inState.copy(beneficiary = AnonymousParty(DUMMY_PUBKEY_2)) } + output { inState.copy(beneficiary = AnonymousParty(DUMMY_PUBKEY_2)) } this `fails with` "the amounts balance" } // This works. - output { inState.copy(beneficiary = DUMMY_PUBKEY_2) } - output { inState.copy(beneficiary = DUMMY_PUBKEY_2) `issued by` MINI_CORP } - command(DUMMY_PUBKEY_1) { Obligation.Commands.Move() } + output { inState.copy(beneficiary = AnonymousParty(DUMMY_PUBKEY_2)) } + output { inState.copy(beneficiary = AnonymousParty(DUMMY_PUBKEY_2)) `issued by` MINI_CORP } + command(CHARLIE.owningKey) { Obligation.Commands.Move() } this.verifies() } } @@ -719,12 +720,12 @@ class ObligationTests { fun multiCurrency() { // Check we can do an atomic currency trade tx. transaction { - val pounds = Obligation.State(Lifecycle.NORMAL, MINI_CORP, megaCorpPoundSettlement, 658.POUNDS.quantity, DUMMY_PUBKEY_2) - input { inState `owned by` DUMMY_PUBKEY_1 } + val pounds = Obligation.State(Lifecycle.NORMAL, MINI_CORP, megaCorpPoundSettlement, 658.POUNDS.quantity, AnonymousParty(DUMMY_PUBKEY_2)) + input { inState `owned by` CHARLIE } input { pounds } - output { inState `owned by` DUMMY_PUBKEY_2 } - output { pounds `owned by` DUMMY_PUBKEY_1 } - command(DUMMY_PUBKEY_1, DUMMY_PUBKEY_2) { Obligation.Commands.Move() } + output { inState `owned by` AnonymousParty(DUMMY_PUBKEY_2) } + output { pounds `owned by` CHARLIE } + command(CHARLIE.owningKey, DUMMY_PUBKEY_2) { Obligation.Commands.Move() } this.verifies() } @@ -733,11 +734,11 @@ class ObligationTests { @Test fun `nettability of settlement contracts`() { val fiveKDollarsFromMegaToMega = Obligation.State(Lifecycle.NORMAL, MEGA_CORP, megaCorpDollarSettlement, - 5000.DOLLARS.quantity, MEGA_CORP_PUBKEY) + 5000.DOLLARS.quantity, MEGA_CORP) val twoKDollarsFromMegaToMini = Obligation.State(Lifecycle.NORMAL, MEGA_CORP, megaCorpDollarSettlement, - 2000.DOLLARS.quantity, MINI_CORP_PUBKEY) + 2000.DOLLARS.quantity, MINI_CORP) val oneKDollarsFromMiniToMega = Obligation.State(Lifecycle.NORMAL, MINI_CORP, megaCorpDollarSettlement, - 1000.DOLLARS.quantity, MEGA_CORP_PUBKEY) + 1000.DOLLARS.quantity, MEGA_CORP) // Obviously states must be nettable with themselves assertEquals(fiveKDollarsFromMegaToMega.bilateralNetState, fiveKDollarsFromMegaToMega.bilateralNetState) @@ -778,9 +779,9 @@ class ObligationTests { @Test fun `extraction of issuance defintion`() { val fiveKDollarsFromMegaToMega = Obligation.State(Lifecycle.NORMAL, MEGA_CORP, megaCorpDollarSettlement, - 5000.DOLLARS.quantity, MEGA_CORP_PUBKEY) + 5000.DOLLARS.quantity, MEGA_CORP) val oneKDollarsFromMiniToMega = Obligation.State(Lifecycle.NORMAL, MINI_CORP, megaCorpDollarSettlement, - 1000.DOLLARS.quantity, MEGA_CORP_PUBKEY) + 1000.DOLLARS.quantity, MEGA_CORP) // Issuance definitions must match the input assertEquals(fiveKDollarsFromMegaToMega.template, megaCorpDollarSettlement) @@ -791,14 +792,14 @@ class ObligationTests { fun `adding two settlement contracts nets them`() { val megaCorpDollarSettlement = Obligation.Terms(trustedCashContract, megaIssuedDollars, fivePm) val fiveKDollarsFromMegaToMini = Obligation.State(Lifecycle.NORMAL, MEGA_CORP, megaCorpDollarSettlement, - 5000.DOLLARS.quantity, MINI_CORP_PUBKEY) + 5000.DOLLARS.quantity, MINI_CORP) val oneKDollarsFromMiniToMega = Obligation.State(Lifecycle.NORMAL, MINI_CORP, megaCorpDollarSettlement, - 1000.DOLLARS.quantity, MEGA_CORP_PUBKEY) + 1000.DOLLARS.quantity, MEGA_CORP) var actual = fiveKDollarsFromMegaToMini.net(fiveKDollarsFromMegaToMini.copy(quantity = 2000.DOLLARS.quantity)) // Both pay from mega to mini, so we add directly var expected = Obligation.State(Lifecycle.NORMAL, MEGA_CORP, megaCorpDollarSettlement, 7000.DOLLARS.quantity, - MINI_CORP_PUBKEY) + MINI_CORP) assertEquals(expected, actual) // Reversing the direction should mean adding the second state subtracts from the first @@ -809,7 +810,7 @@ class ObligationTests { // Trying to add an incompatible state must throw an error assertFailsWith(IllegalArgumentException::class) { fiveKDollarsFromMegaToMini.net(Obligation.State(Lifecycle.NORMAL, MINI_CORP, megaCorpDollarSettlement, 1000.DOLLARS.quantity, - MINI_CORP_PUBKEY)) + MINI_CORP)) } } @@ -817,9 +818,9 @@ class ObligationTests { fun `extracting amounts due between parties from a list of states`() { val megaCorpDollarSettlement = Obligation.Terms(trustedCashContract, megaIssuedDollars, fivePm) val fiveKDollarsFromMegaToMini = Obligation.State(Lifecycle.NORMAL, MEGA_CORP, megaCorpDollarSettlement, - 5000.DOLLARS.quantity, MINI_CORP_PUBKEY) + 5000.DOLLARS.quantity, MINI_CORP) val amount = fiveKDollarsFromMegaToMini.amount - val expected: Map, Amount>> = mapOf(Pair(Pair(MEGA_CORP_PUBKEY, MINI_CORP_PUBKEY), Amount(amount.quantity, amount.token.product))) + val expected: Map, Amount>> = mapOf(Pair(Pair(MEGA_CORP, MINI_CORP), Amount(amount.quantity, amount.token.product))) val actual = extractAmountsDue(megaCorpDollarSettlement, listOf(fiveKDollarsFromMegaToMini)) assertEquals(expected, actual) } @@ -827,24 +828,24 @@ class ObligationTests { @Test fun `netting equal balances due between parties`() { // Now try it with two balances, which cancel each other out - val balanced: Map, Amount> = mapOf( - Pair(Pair(ALICE_PUBKEY, BOB_PUBKEY), Amount(100000000, GBP)), - Pair(Pair(BOB_PUBKEY, ALICE_PUBKEY), Amount(100000000, GBP)) + val balanced: Map, Amount> = mapOf( + Pair(Pair(ALICE, BOB), Amount(100000000, GBP)), + Pair(Pair(BOB, ALICE), Amount(100000000, GBP)) ) - val expected: Map, Amount> = emptyMap() // Zero balances are stripped before returning - val actual: Map, Amount> = netAmountsDue(balanced) + val expected: Map, Amount> = emptyMap() // Zero balances are stripped before returning + val actual: Map, Amount> = netAmountsDue(balanced) assertEquals(expected, actual) } @Test fun `netting difference balances due between parties`() { // Now try it with two balances, which cancel each other out - val balanced: Map, Amount> = mapOf( - Pair(Pair(ALICE_PUBKEY, BOB_PUBKEY), Amount(100000000, GBP)), - Pair(Pair(BOB_PUBKEY, ALICE_PUBKEY), Amount(200000000, GBP)) + val balanced: Map, Amount> = mapOf( + Pair(Pair(ALICE, BOB), Amount(100000000, GBP)), + Pair(Pair(BOB, ALICE), Amount(200000000, GBP)) ) - val expected: Map, Amount> = mapOf( - Pair(Pair(BOB_PUBKEY, ALICE_PUBKEY), Amount(100000000, GBP)) + val expected: Map, Amount> = mapOf( + Pair(Pair(BOB, ALICE), Amount(100000000, GBP)) ) val actual = netAmountsDue(balanced) assertEquals(expected, actual) @@ -852,16 +853,16 @@ class ObligationTests { @Test fun `summing empty balances due between parties`() { - val empty = emptyMap, Amount>() - val expected = emptyMap() + val empty = emptyMap, Amount>() + val expected = emptyMap() val actual = sumAmountsDue(empty) assertEquals(expected, actual) } @Test fun `summing balances due between parties`() { - val simple: Map, Amount> = mapOf(Pair(Pair(ALICE_PUBKEY, BOB_PUBKEY), Amount(100000000, GBP))) - val expected: Map = mapOf(Pair(ALICE_PUBKEY, -100000000L), Pair(BOB_PUBKEY, 100000000L)) + val simple: Map, Amount> = mapOf(Pair(Pair(ALICE, BOB), Amount(100000000, GBP))) + val expected: Map = mapOf(Pair(ALICE, -100000000L), Pair(BOB, 100000000L)) val actual = sumAmountsDue(simple) assertEquals(expected, actual) } @@ -869,11 +870,11 @@ class ObligationTests { @Test fun `summing balances due between parties which net to zero`() { // Now try it with two balances, which cancel each other out - val balanced: Map, Amount> = mapOf( - Pair(Pair(ALICE_PUBKEY, BOB_PUBKEY), Amount(100000000, GBP)), - Pair(Pair(BOB_PUBKEY, ALICE_PUBKEY), Amount(100000000, GBP)) + val balanced: Map, Amount> = mapOf( + Pair(Pair(ALICE, BOB), Amount(100000000, GBP)), + Pair(Pair(BOB, ALICE), Amount(100000000, GBP)) ) - val expected: Map = emptyMap() // Zero balances are stripped before returning + val expected: Map = emptyMap() // Zero balances are stripped before returning val actual = sumAmountsDue(balanced) assertEquals(expected, actual) } diff --git a/finance/src/test/kotlin/net/corda/contracts/testing/Generators.kt b/finance/src/test/kotlin/net/corda/contracts/testing/Generators.kt index 1deab780cd..1b9789bc04 100644 --- a/finance/src/test/kotlin/net/corda/contracts/testing/Generators.kt +++ b/finance/src/test/kotlin/net/corda/contracts/testing/Generators.kt @@ -10,6 +10,7 @@ import net.corda.core.contracts.CommandData import net.corda.core.contracts.ContractState import net.corda.core.contracts.TransactionType import net.corda.core.crypto.NullSignature +import net.corda.core.identity.AnonymousParty import net.corda.core.testing.* import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.WireTransaction @@ -25,7 +26,7 @@ class ContractStateGenerator : Generator(ContractState::class.jav override fun generate(random: SourceOfRandomness, status: GenerationStatus): ContractState { return Cash.State( amount = AmountGenerator(IssuedGenerator(CurrencyGenerator())).generate(random, status), - owner = PublicKeyGenerator().generate(random, status) + owner = AnonymousParty(PublicKeyGenerator().generate(random, status)) ) } } diff --git a/finance/src/test/kotlin/net/corda/flows/CashPaymentFlowTests.kt b/finance/src/test/kotlin/net/corda/flows/CashPaymentFlowTests.kt index eb2c99c836..33f15b0898 100644 --- a/finance/src/test/kotlin/net/corda/flows/CashPaymentFlowTests.kt +++ b/finance/src/test/kotlin/net/corda/flows/CashPaymentFlowTests.kt @@ -54,8 +54,8 @@ class CashPaymentFlowTests { net.runNetwork() val paymentTx = future.getOrThrow() val states = paymentTx.tx.outputs.map { it.data }.filterIsInstance() - val ourState = states.single { it.owner != payTo.owningKey } - val paymentState = states.single { it.owner == payTo.owningKey } + val ourState = states.single { it.owner.owningKey != payTo.owningKey } + val paymentState = states.single { it.owner.owningKey == payTo.owningKey } assertEquals(expected.`issued by`(bankOfCorda.ref(ref)), paymentState.amount) } diff --git a/node-schemas/src/test/kotlin/net/corda/node/services/vault/schemas/VaultSchemaTest.kt b/node-schemas/src/test/kotlin/net/corda/node/services/vault/schemas/VaultSchemaTest.kt index f2899c2102..05c5c3f903 100644 --- a/node-schemas/src/test/kotlin/net/corda/node/services/vault/schemas/VaultSchemaTest.kt +++ b/node-schemas/src/test/kotlin/net/corda/node/services/vault/schemas/VaultSchemaTest.kt @@ -11,7 +11,11 @@ import io.requery.rx.KotlinRxEntityStore import io.requery.sql.* import io.requery.sql.platform.Generic import net.corda.core.contracts.* -import net.corda.core.crypto.* +import net.corda.core.crypto.CompositeKey +import net.corda.core.crypto.SecureHash +import net.corda.core.crypto.generateKeyPair +import net.corda.core.crypto.toBase58String +import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.node.services.Vault import net.corda.core.schemas.requery.converters.InstantConverter @@ -19,17 +23,16 @@ import net.corda.core.schemas.requery.converters.VaultStateStatusConverter import net.corda.core.serialization.deserialize import net.corda.core.serialization.serialize import net.corda.core.transactions.LedgerTransaction +import net.corda.core.utilities.ALICE +import net.corda.core.utilities.BOB import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.DUMMY_NOTARY_KEY -import net.corda.core.utilities.DUMMY_PUBKEY_1 -import net.corda.core.utilities.DUMMY_PUBKEY_2 import org.h2.jdbcx.JdbcDataSource import org.junit.After import org.junit.Assert import org.junit.Before import org.junit.Test import rx.Observable -import java.security.PublicKey import java.time.Instant import java.util.* import java.util.concurrent.CountDownLatch @@ -81,12 +84,12 @@ class VaultSchemaTest { private class VaultNoopContract : Contract { override val legalContractReference = SecureHash.sha256("") - data class VaultNoopState(override val owner: PublicKey) : OwnableState { + data class VaultNoopState(override val owner: AbstractParty) : OwnableState { override val contract = VaultNoopContract() - override val participants: List + override val participants: List get() = listOf(owner) - override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Create(), copy(owner = newOwner)) + override fun withNewOwner(newOwner: AbstractParty) = Pair(Commands.Create(), copy(owner = newOwner)) } interface Commands : CommandData { @@ -101,10 +104,10 @@ class VaultSchemaTest { private fun setupDummyData() { // dummy Transaction val notary: Party = DUMMY_NOTARY - val inState1 = TransactionState(DummyContract.SingleOwnerState(0, DUMMY_PUBKEY_1), notary) + val inState1 = TransactionState(DummyContract.SingleOwnerState(0, ALICE), notary) val inState2 = TransactionState(DummyContract.MultiOwnerState(0, - listOf(DUMMY_PUBKEY_1, DUMMY_PUBKEY_2)), notary) - val inState3 = TransactionState(VaultNoopContract.VaultNoopState(DUMMY_PUBKEY_1), notary) + listOf(ALICE, BOB)), notary) + val inState3 = TransactionState(VaultNoopContract.VaultNoopState(ALICE), notary) val outState1 = inState1.copy() val outState2 = inState2.copy() val outState3 = inState3.copy() @@ -132,9 +135,9 @@ class VaultSchemaTest { private fun createTxnWithTwoStateTypes(): LedgerTransaction { val notary: Party = DUMMY_NOTARY - val inState1 = TransactionState(DummyContract.SingleOwnerState(0, DUMMY_PUBKEY_1), notary) + val inState1 = TransactionState(DummyContract.SingleOwnerState(0, ALICE), notary) val inState2 = TransactionState(DummyContract.MultiOwnerState(0, - listOf(DUMMY_PUBKEY_1, DUMMY_PUBKEY_2)), notary) + listOf(ALICE, BOB)), notary) val outState1 = inState1.copy() val outState2 = inState2.copy() val state1TxHash = SecureHash.randomSHA256() diff --git a/node/src/integration-test/kotlin/net/corda/node/services/BFTNotaryServiceTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/BFTNotaryServiceTests.kt index 6857a64543..05a6439780 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/BFTNotaryServiceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/BFTNotaryServiceTests.kt @@ -57,7 +57,7 @@ class BFTNotaryServiceTests : NodeBasedTest() { firstSpend.resultFuture.getOrThrow() val secondSpendTx = TransactionType.General.Builder(notaryParty).withItems(inputState).run { - val dummyState = DummyContract.SingleOwnerState(0, alice.info.legalIdentity.owningKey) + val dummyState = DummyContract.SingleOwnerState(0, alice.info.legalIdentity) addOutputState(dummyState) signWith(aliceKey) toSignedTransaction(false) diff --git a/node/src/integration-test/kotlin/net/corda/node/services/RaftNotaryServiceTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/RaftNotaryServiceTests.kt index 3e5edba828..9ed86a7c72 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/RaftNotaryServiceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/RaftNotaryServiceTests.kt @@ -46,7 +46,7 @@ class RaftNotaryServiceTests : NodeBasedTest() { firstSpend.resultFuture.getOrThrow() val secondSpendTx = TransactionType.General.Builder(notaryParty).withItems(inputState).run { - val dummyState = DummyContract.SingleOwnerState(0, alice.info.legalIdentity.owningKey) + val dummyState = DummyContract.SingleOwnerState(0, alice.info.legalIdentity) addOutputState(dummyState) signWith(aliceKey) toSignedTransaction(false) diff --git a/node/src/main/kotlin/net/corda/node/services/CoreFlowHandlers.kt b/node/src/main/kotlin/net/corda/node/services/CoreFlowHandlers.kt index 354b97d438..33658c855c 100644 --- a/node/src/main/kotlin/net/corda/node/services/CoreFlowHandlers.kt +++ b/node/src/main/kotlin/net/corda/node/services/CoreFlowHandlers.kt @@ -115,7 +115,7 @@ class ContractUpgradeHandler(otherSide: Party) : AbstractStateReplacementFlow.Ac val proposedTx = proposal.stx.tx val expectedTx = ContractUpgradeFlow.assembleBareTx(oldStateAndRef, proposal.modification).toWireTransaction() requireThat { - "The instigator is one of the participants" using (otherSide.owningKey in oldStateAndRef.state.data.participants) + "The instigator is one of the participants" using (otherSide in oldStateAndRef.state.data.participants) "The proposed upgrade ${proposal.modification.javaClass} is a trusted upgrade path" using (proposal.modification == authorisedUpgrade) "The proposed tx matches the expected tx for this upgrade" using (proposedTx == expectedTx) } 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 38992442e2..77b0d01c2a 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 @@ -3,6 +3,7 @@ package net.corda.node.services.identity import net.corda.core.contracts.PartyAndReference import net.corda.core.contracts.requireThat import net.corda.core.crypto.toStringShort +import net.corda.core.identity.AbstractParty import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import net.corda.core.node.services.IdentityService @@ -16,7 +17,6 @@ import java.security.cert.* import java.util.* import java.util.concurrent.ConcurrentHashMap import javax.annotation.concurrent.ThreadSafe -import javax.security.auth.x500.X500Principal /** * Simple identity service which caches parties and provides functionality for efficient lookup. @@ -44,7 +44,7 @@ class InMemoryIdentityService : SingletonSerializeAsToken(), IdentityService { @Deprecated("Use partyFromX500Name") override fun partyFromName(name: String): Party? = principalToParties[X500Name(name)] override fun partyFromX500Name(principal: X500Name): Party? = principalToParties[principal] - override fun partyFromAnonymous(party: AnonymousParty): Party? = partyFromKey(party.owningKey) + override fun partyFromAnonymous(party: AbstractParty): Party? = partyFromKey(party.owningKey) override fun partyFromAnonymous(partyRef: PartyAndReference) = partyFromAnonymous(partyRef.party) @Throws(IdentityService.UnknownAnonymousPartyException::class) diff --git a/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt b/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt index d86b8c7ce0..71c48a6792 100644 --- a/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt +++ b/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt @@ -11,11 +11,12 @@ import io.requery.kotlin.notNull import io.requery.query.RowExpression import net.corda.contracts.asset.Cash import net.corda.contracts.asset.OnLedgerAsset -import net.corda.contracts.clause.AbstractConserveAmount import net.corda.core.ThreadBox import net.corda.core.bufferUntilSubscribed import net.corda.core.contracts.* -import net.corda.core.crypto.* +import net.corda.core.crypto.SecureHash +import net.corda.core.crypto.containsAny +import net.corda.core.crypto.toBase58String import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.node.ServiceHub @@ -468,7 +469,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P @Suspendable override fun generateSpend(tx: TransactionBuilder, amount: Amount, - to: PublicKey, + to: AbstractParty, onlyFromParties: Set?): Pair> { // Retrieve unspent and unlocked cash states that meet our spending criteria. val acceptableCoins = unconsumedStatesForSpending(amount, onlyFromParties, tx.notary, tx.lockId) @@ -477,7 +478,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P { Cash().generateMoveCommand() }) } - private fun deriveState(txState: TransactionState, amount: Amount>, owner: PublicKey) + private fun deriveState(txState: TransactionState, amount: Amount>, owner: AbstractParty) = txState.copy(data = txState.data.copy(amount = amount, owner = owner)) private fun makeUpdate(tx: WireTransaction, ourKeys: Set): Vault.Update { @@ -528,7 +529,7 @@ class NodeVaultService(private val services: ServiceHub, dataSourceProperties: P } private fun isRelevant(state: ContractState, ourKeys: Set) = when (state) { - is OwnableState -> state.owner.containsAny(ourKeys) + is OwnableState -> state.owner.owningKey.containsAny(ourKeys) // It's potentially of interest to the vault is LinearState -> state.isRelevant(ourKeys) else -> false diff --git a/node/src/test/kotlin/net/corda/node/CordaRPCOpsImplTest.kt b/node/src/test/kotlin/net/corda/node/CordaRPCOpsImplTest.kt index c5c8c16129..da63771508 100644 --- a/node/src/test/kotlin/net/corda/node/CordaRPCOpsImplTest.kt +++ b/node/src/test/kotlin/net/corda/node/CordaRPCOpsImplTest.kt @@ -91,7 +91,7 @@ class CordaRPCOpsImplTest { val expectedState = Cash.State(Amount(quantity, Issued(aliceNode.info.legalIdentity.ref(ref), GBP)), - recipient.owningKey) + recipient) var issueSmId: StateMachineRunId? = null stateMachineUpdates.expectEvents { 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 ab5663be20..1fe5918362 100644 --- a/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt +++ b/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt @@ -14,6 +14,7 @@ import net.corda.core.flows.FlowStateMachine import net.corda.core.flows.InitiatingFlow import net.corda.core.flows.StateMachineRunId import net.corda.core.getOrThrow +import net.corda.core.identity.AbstractParty import net.corda.core.map import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.node.NodeInfo @@ -97,7 +98,7 @@ class TwoPartyTradeFlowTests { } val alicesFakePaper = aliceNode.database.transaction { - fillUpForSeller(false, aliceNode.info.legalIdentity.owningKey, + fillUpForSeller(false, aliceNode.info.legalIdentity, 1200.DOLLARS `issued by` DUMMY_CASH_ISSUER, null, notaryNode.info.notaryIdentity).second } @@ -144,7 +145,7 @@ class TwoPartyTradeFlowTests { } val alicesFakePaper = aliceNode.database.transaction { - fillUpForSeller(false, aliceNode.info.legalIdentity.owningKey, + fillUpForSeller(false, aliceNode.info.legalIdentity, 1200.DOLLARS `issued by` DUMMY_CASH_ISSUER, null, notaryNode.info.notaryIdentity).second } @@ -195,7 +196,7 @@ class TwoPartyTradeFlowTests { bobNode.services.fillWithSomeTestCash(2000.DOLLARS, outputNotary = notaryNode.info.notaryIdentity) } val alicesFakePaper = aliceNode.database.transaction { - fillUpForSeller(false, aliceNode.info.legalIdentity.owningKey, + fillUpForSeller(false, aliceNode.info.legalIdentity, 1200.DOLLARS `issued by` DUMMY_CASH_ISSUER, null, notaryNode.info.notaryIdentity).second } insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, aliceKey, notaryKey) @@ -301,6 +302,7 @@ class TwoPartyTradeFlowTests { val notaryNode = net.createNotaryNode(null, DUMMY_NOTARY.name) val aliceNode = makeNodeWithTracking(notaryNode.info.address, ALICE.name) val bobNode = makeNodeWithTracking(notaryNode.info.address, BOB.name) + val alice = aliceNode.info.legalIdentity val aliceKey = aliceNode.services.legalIdentityKey ledger(aliceNode.services) { @@ -317,12 +319,13 @@ class TwoPartyTradeFlowTests { } val extraKey = bobNode.keyManagement.freshKey() - val bobsFakeCash = fillUpForBuyer(false, extraKey.public, + val extraPublicKey = extraKey.public + val bobsFakeCash = fillUpForBuyer(false, AnonymousParty(extraPublicKey), DUMMY_CASH_ISSUER.party, notaryNode.info.notaryIdentity).second val bobsSignedTxns = insertFakeTransactions(bobsFakeCash, bobNode, notaryNode, bobNode.services.legalIdentityKey, extraKey) val alicesFakePaper = aliceNode.database.transaction { - fillUpForSeller(false, aliceNode.info.legalIdentity.owningKey, + fillUpForSeller(false, alice, 1200.DOLLARS `issued by` DUMMY_CASH_ISSUER, attachmentID, notaryNode.info.notaryIdentity).second } val alicesSignedTxns = insertFakeTransactions(alicesFakePaper, aliceNode, notaryNode, aliceKey) @@ -416,13 +419,14 @@ class TwoPartyTradeFlowTests { attachment(ByteArrayInputStream(stream.toByteArray())) } - val bobsFakeCash = fillUpForBuyer(false, bobNode.keyManagement.freshKey().public, + val bobsKey = bobNode.keyManagement.freshKey().public + val bobsFakeCash = fillUpForBuyer(false, AnonymousParty(bobsKey), DUMMY_CASH_ISSUER.party, notaryNode.info.notaryIdentity).second insertFakeTransactions(bobsFakeCash, bobNode, notaryNode) val alicesFakePaper = aliceNode.database.transaction { - fillUpForSeller(false, aliceNode.info.legalIdentity.owningKey, + fillUpForSeller(false, aliceNode.info.legalIdentity, 1200.DOLLARS `issued by` DUMMY_CASH_ISSUER, attachmentID, notaryNode.info.notaryIdentity).second } @@ -520,14 +524,16 @@ class TwoPartyTradeFlowTests { val notaryNode = net.createNotaryNode(null, DUMMY_NOTARY.name) val aliceNode = net.createPartyNode(notaryNode.info.address, ALICE.name) val bobNode = net.createPartyNode(notaryNode.info.address, BOB.name) + val alice = aliceNode.info.legalIdentity val aliceKey = aliceNode.services.legalIdentityKey + val bob = bobNode.info.legalIdentity val bobKey = bobNode.services.legalIdentityKey val issuer = MEGA_CORP.ref(1, 2, 3) - val bobsBadCash = fillUpForBuyer(bobError, bobKey.public, DUMMY_CASH_ISSUER.party, + val bobsBadCash = fillUpForBuyer(bobError, bob, DUMMY_CASH_ISSUER.party, notaryNode.info.notaryIdentity).second val alicesFakePaper = aliceNode.database.transaction { - fillUpForSeller(aliceError, aliceNode.info.legalIdentity.owningKey, + fillUpForSeller(aliceError, alice, 1200.DOLLARS `issued by` issuer, null, notaryNode.info.notaryIdentity).second } @@ -571,16 +577,16 @@ class TwoPartyTradeFlowTests { private fun LedgerDSL.fillUpForBuyer( withError: Boolean, - owner: PublicKey, - issuer: AnonymousParty, + owner: AbstractParty, + issuer: AbstractParty, notary: Party): Pair, List> { - val interimOwnerKey = MEGA_CORP_PUBKEY + val interimOwner = MEGA_CORP // Bob (Buyer) has some cash he got from the Bank of Elbonia, Alice (Seller) has some commercial paper she // wants to sell to Bob. val eb1 = transaction(transactionBuilder = TransactionBuilder(notary = notary)) { // Issued money to itself. - output("elbonian money 1", notary = notary) { 800.DOLLARS.CASH `issued by` issuer `owned by` interimOwnerKey } - output("elbonian money 2", notary = notary) { 1000.DOLLARS.CASH `issued by` issuer `owned by` interimOwnerKey } + output("elbonian money 1", notary = notary) { 800.DOLLARS.CASH `issued by` issuer `owned by` interimOwner } + output("elbonian money 2", notary = notary) { 1000.DOLLARS.CASH `issued by` issuer `owned by` interimOwner } if (!withError) { command(issuer.owningKey) { Cash.Commands.Issue() } } else { @@ -599,15 +605,15 @@ class TwoPartyTradeFlowTests { val bc1 = transaction(transactionBuilder = TransactionBuilder(notary = notary)) { input("elbonian money 1") output("bob cash 1", notary = notary) { 800.DOLLARS.CASH `issued by` issuer `owned by` owner } - command(interimOwnerKey) { Cash.Commands.Move() } + command(interimOwner.owningKey) { Cash.Commands.Move() } this.verifies() } val bc2 = transaction(transactionBuilder = TransactionBuilder(notary = notary)) { input("elbonian money 2") output("bob cash 2", notary = notary) { 300.DOLLARS.CASH `issued by` issuer `owned by` owner } - output(notary = notary) { 700.DOLLARS.CASH `issued by` issuer `owned by` interimOwnerKey } // Change output. - command(interimOwnerKey) { Cash.Commands.Move() } + output(notary = notary) { 700.DOLLARS.CASH `issued by` issuer `owned by` interimOwner } // Change output. + command(interimOwner.owningKey) { Cash.Commands.Move() } this.verifies() } @@ -617,7 +623,7 @@ class TwoPartyTradeFlowTests { private fun LedgerDSL.fillUpForSeller( withError: Boolean, - owner: PublicKey, + owner: AbstractParty, amount: Amount>, attachmentID: SecureHash?, notary: Party): Pair, List> { diff --git a/node/src/test/kotlin/net/corda/node/services/NotaryChangeTests.kt b/node/src/test/kotlin/net/corda/node/services/NotaryChangeTests.kt index 2581b99266..ff2c82ffee 100644 --- a/node/src/test/kotlin/net/corda/node/services/NotaryChangeTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/NotaryChangeTests.kt @@ -123,9 +123,9 @@ class NotaryChangeTests { val owner = node.info.legalIdentity.ref(0) val notary = notaryNode.info.notaryIdentity - val stateA = DummyContract.SingleOwnerState(Random().nextInt(), owner.party.owningKey) - val stateB = DummyContract.SingleOwnerState(Random().nextInt(), owner.party.owningKey) - val stateC = DummyContract.SingleOwnerState(Random().nextInt(), owner.party.owningKey) + val stateA = DummyContract.SingleOwnerState(Random().nextInt(), owner.party) + val stateB = DummyContract.SingleOwnerState(Random().nextInt(), owner.party) + val stateC = DummyContract.SingleOwnerState(Random().nextInt(), owner.party) val tx = TransactionType.General.Builder(null).apply { addCommand(Command(DummyContract.Commands.Create(), owner.party.owningKey)) @@ -162,7 +162,7 @@ fun issueState(node: AbstractNode, notaryNode: AbstractNode): StateAndRef<*> { fun issueMultiPartyState(nodeA: AbstractNode, nodeB: AbstractNode, notaryNode: AbstractNode): StateAndRef { val state = TransactionState(DummyContract.MultiOwnerState(0, - listOf(nodeA.info.legalIdentity.owningKey, nodeB.info.legalIdentity.owningKey)), notaryNode.info.notaryIdentity) + listOf(nodeA.info.legalIdentity, nodeB.info.legalIdentity)), notaryNode.info.notaryIdentity) val tx = TransactionType.NotaryChange.Builder(notaryNode.info.notaryIdentity).withItems(state) val nodeAKey = nodeA.services.legalIdentityKey val nodeBKey = nodeB.services.legalIdentityKey diff --git a/node/src/test/kotlin/net/corda/node/services/database/RequeryConfigurationTest.kt b/node/src/test/kotlin/net/corda/node/services/database/RequeryConfigurationTest.kt index f27f519738..447769ea45 100644 --- a/node/src/test/kotlin/net/corda/node/services/database/RequeryConfigurationTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/database/RequeryConfigurationTest.kt @@ -10,6 +10,7 @@ import net.corda.core.crypto.DigitalSignature import net.corda.core.crypto.NullPublicKey import net.corda.core.crypto.SecureHash import net.corda.core.crypto.toBase58String +import net.corda.core.identity.AnonymousParty import net.corda.core.node.services.Vault import net.corda.core.serialization.serialize import net.corda.core.serialization.storageKryo @@ -129,7 +130,7 @@ class RequeryConfigurationTest { index = txnState.index stateStatus = Vault.StateStatus.UNCONSUMED contractStateClassName = DummyContract.SingleOwnerState::class.java.name - contractState = DummyContract.SingleOwnerState(owner = DUMMY_PUBKEY_1).serialize(storageKryo()).bytes + contractState = DummyContract.SingleOwnerState(owner = AnonymousParty(DUMMY_PUBKEY_1)).serialize(storageKryo()).bytes notaryName = txn.tx.notary!!.name.toString() notaryKey = txn.tx.notary!!.owningKey.toBase58String() recordedTime = Instant.now() diff --git a/node/src/test/kotlin/net/corda/node/services/events/NodeSchedulerServiceTest.kt b/node/src/test/kotlin/net/corda/node/services/events/NodeSchedulerServiceTest.kt index ee3055c3a8..c2ff4350af 100644 --- a/node/src/test/kotlin/net/corda/node/services/events/NodeSchedulerServiceTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/events/NodeSchedulerServiceTest.kt @@ -5,6 +5,7 @@ import net.corda.core.days import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogicRef import net.corda.core.flows.FlowLogicRefFactory +import net.corda.core.identity.AbstractParty import net.corda.core.node.ServiceHub import net.corda.core.node.services.VaultService import net.corda.core.serialization.SingletonSerializeAsToken @@ -113,7 +114,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() { } class TestState(val flowLogicRef: FlowLogicRef, val instant: Instant) : LinearState, SchedulableState { - override val participants: List + override val participants: List get() = throw UnsupportedOperationException() override val linearId = UniqueIdentifier() diff --git a/node/src/test/kotlin/net/corda/node/services/events/ScheduledFlowTests.kt b/node/src/test/kotlin/net/corda/node/services/events/ScheduledFlowTests.kt index 3d79ad6ed7..301ea3b9a7 100644 --- a/node/src/test/kotlin/net/corda/node/services/events/ScheduledFlowTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/events/ScheduledFlowTests.kt @@ -2,12 +2,13 @@ package net.corda.node.services.events import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.* -import net.corda.core.identity.Party import net.corda.core.crypto.containsAny import net.corda.core.flows.FlowInitiator import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogicRefFactory import net.corda.core.flows.SchedulableFlow +import net.corda.core.identity.AbstractParty +import net.corda.core.identity.Party import net.corda.core.node.services.ServiceInfo import net.corda.core.node.services.linearHeadsOfType import net.corda.core.utilities.DUMMY_NOTARY @@ -46,10 +47,10 @@ class ScheduledFlowTests { } } - override val participants: List = listOf(source.owningKey, destination.owningKey) + override val participants: List = listOf(source, destination) override fun isRelevant(ourKeys: Set): Boolean { - return participants.any { it.containsAny(ourKeys) } + return participants.any { it.owningKey.containsAny(ourKeys) } } } diff --git a/node/src/test/kotlin/net/corda/node/services/persistence/DataVendingServiceTests.kt b/node/src/test/kotlin/net/corda/node/services/persistence/DataVendingServiceTests.kt index 9064db174e..2cd6c54c5e 100644 --- a/node/src/test/kotlin/net/corda/node/services/persistence/DataVendingServiceTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/persistence/DataVendingServiceTests.kt @@ -37,7 +37,7 @@ class DataVendingServiceTests { @Test fun `notify of transaction`() { val (vaultServiceNode, registerNode) = network.createTwoNodes() - val beneficiary = vaultServiceNode.info.legalIdentity.owningKey + val beneficiary = vaultServiceNode.info.legalIdentity val deposit = registerNode.info.legalIdentity.ref(1) network.runNetwork() @@ -67,7 +67,7 @@ class DataVendingServiceTests { @Test fun `notify failure`() { val (vaultServiceNode, registerNode) = network.createTwoNodes() - val beneficiary = vaultServiceNode.info.legalIdentity.owningKey + val beneficiary = vaultServiceNode.info.legalIdentity val deposit = MEGA_CORP.ref(1) network.runNetwork() diff --git a/node/src/test/kotlin/net/corda/node/services/schema/HibernateObserverTests.kt b/node/src/test/kotlin/net/corda/node/services/schema/HibernateObserverTests.kt index 75c468dd4f..e862b3fc74 100644 --- a/node/src/test/kotlin/net/corda/node/services/schema/HibernateObserverTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/schema/HibernateObserverTests.kt @@ -6,6 +6,7 @@ import net.corda.core.contracts.StateRef import net.corda.core.contracts.TransactionState import net.corda.core.crypto.CompositeKey import net.corda.core.crypto.SecureHash +import net.corda.core.identity.AbstractParty import net.corda.core.node.services.Vault import net.corda.core.schemas.MappedSchema import net.corda.core.schemas.PersistentState @@ -86,7 +87,7 @@ class HibernateObserverTests { override val contract: Contract get() = throw UnsupportedOperationException() - override val participants: List + override val participants: List get() = throw UnsupportedOperationException() } diff --git a/node/src/test/kotlin/net/corda/node/services/vault/NodeVaultServiceTest.kt b/node/src/test/kotlin/net/corda/node/services/vault/NodeVaultServiceTest.kt index 8190cd02cf..4afc6987e7 100644 --- a/node/src/test/kotlin/net/corda/node/services/vault/NodeVaultServiceTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/vault/NodeVaultServiceTest.kt @@ -4,6 +4,7 @@ import net.corda.contracts.asset.Cash import net.corda.contracts.asset.DUMMY_CASH_ISSUER import net.corda.contracts.testing.fillWithSomeTestCash import net.corda.core.contracts.* +import net.corda.core.identity.AnonymousParty import net.corda.core.node.services.StatesNotAvailableException import net.corda.core.node.services.TxWritableStorageService import net.corda.core.node.services.VaultService @@ -401,11 +402,11 @@ class NodeVaultServiceTest { fun addNoteToTransaction() { database.transaction { - val freshKey = services.legalIdentityKey + val freshKey = services.legalIdentityKey.public // Issue a txn to Send us some Money val usefulTX = TransactionType.General.Builder(null).apply { - Cash().generateIssue(this, 100.DOLLARS `issued by` MEGA_CORP.ref(1), freshKey.public, DUMMY_NOTARY) + Cash().generateIssue(this, 100.DOLLARS `issued by` MEGA_CORP.ref(1), AnonymousParty(freshKey), DUMMY_NOTARY) signWith(MEGA_CORP_KEY) }.toSignedTransaction() @@ -418,7 +419,7 @@ class NodeVaultServiceTest { // Issue more Money (GBP) val anotherTX = TransactionType.General.Builder(null).apply { - Cash().generateIssue(this, 200.POUNDS `issued by` MEGA_CORP.ref(1), freshKey.public, DUMMY_NOTARY) + Cash().generateIssue(this, 200.POUNDS `issued by` MEGA_CORP.ref(1), AnonymousParty(freshKey), DUMMY_NOTARY) signWith(MEGA_CORP_KEY) }.toSignedTransaction() diff --git a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt index 7ee8bcf34d..db8374cf34 100644 --- a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt @@ -206,9 +206,9 @@ class VaultQueryTests { fun `unconsumed states by participants`() { database.transaction { - services.fillWithSomeTestLinearStates(2, UniqueIdentifier("TEST"), participants = listOf(MEGA_CORP_PUBKEY, MINI_CORP_PUBKEY)) - services.fillWithSomeTestDeals(listOf("456"), 3, participants = listOf(MEGA_CORP_PUBKEY, BIG_CORP_PUBKEY)) - services.fillWithSomeTestDeals(listOf("123", "789"), participants = listOf(BIG_CORP_PUBKEY, MINI_CORP_PUBKEY)) + services.fillWithSomeTestLinearStates(2, UniqueIdentifier("TEST"), participants = listOf(MEGA_CORP, MINI_CORP)) + services.fillWithSomeTestDeals(listOf("456"), 3, participants = listOf(MEGA_CORP, BIG_CORP)) + services.fillWithSomeTestDeals(listOf("123", "789"), participants = listOf(BIG_CORP, MINI_CORP)) // DOCSTART VaultQueryExample5 val criteria = VaultQueryCriteria(participantIdentities = listOf(MEGA_CORP.name, MINI_CORP.name)) diff --git a/node/src/test/kotlin/net/corda/node/services/vault/VaultWithCashTest.kt b/node/src/test/kotlin/net/corda/node/services/vault/VaultWithCashTest.kt index fe87a6aee9..e06cdab258 100644 --- a/node/src/test/kotlin/net/corda/node/services/vault/VaultWithCashTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/vault/VaultWithCashTest.kt @@ -4,17 +4,17 @@ import net.corda.contracts.asset.Cash import net.corda.contracts.asset.DUMMY_CASH_ISSUER import net.corda.contracts.testing.* import net.corda.core.contracts.* +import net.corda.core.identity.AnonymousParty import net.corda.core.node.services.VaultService import net.corda.core.node.services.consumedStates import net.corda.core.node.services.unconsumedStates import net.corda.core.transactions.SignedTransaction -import net.corda.core.utilities.BOB_KEY +import net.corda.core.utilities.BOB import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.DUMMY_NOTARY_KEY import net.corda.core.utilities.LogHelper import net.corda.node.utilities.configureDatabase import net.corda.node.utilities.transaction -import net.corda.testing.BOB_PUBKEY import net.corda.testing.MEGA_CORP import net.corda.testing.MEGA_CORP_KEY import net.corda.testing.node.MockServices @@ -79,7 +79,7 @@ class VaultWithCashTest { val state = w[0].state.data assertEquals(30.45.DOLLARS `issued by` DUMMY_CASH_ISSUER, state.amount) - assertEquals(services.key.public, state.owner) + assertEquals(services.key.public, state.owner.owningKey) assertEquals(34.70.DOLLARS `issued by` DUMMY_CASH_ISSUER, (w[2].state.data).amount) assertEquals(34.85.DOLLARS `issued by` DUMMY_CASH_ISSUER, (w[1].state.data).amount) @@ -91,8 +91,9 @@ class VaultWithCashTest { database.transaction { // A tx that sends us money. val freshKey = services.keyManagementService.freshKey() + val freshPublicKey = freshKey.public val usefulTX = TransactionType.General.Builder(null).apply { - Cash().generateIssue(this, 100.DOLLARS `issued by` MEGA_CORP.ref(1), freshKey.public, DUMMY_NOTARY) + Cash().generateIssue(this, 100.DOLLARS `issued by` MEGA_CORP.ref(1), AnonymousParty(freshPublicKey), DUMMY_NOTARY) signWith(MEGA_CORP_KEY) }.toSignedTransaction() @@ -101,7 +102,7 @@ class VaultWithCashTest { // A tx that spends our money. val spendTX = TransactionType.General.Builder(DUMMY_NOTARY).apply { - vault.generateSpend(this, 80.DOLLARS, BOB_PUBKEY) + vault.generateSpend(this, 80.DOLLARS, BOB) signWith(freshKey) signWith(DUMMY_NOTARY_KEY) }.toSignedTransaction() @@ -110,7 +111,7 @@ class VaultWithCashTest { // A tx that doesn't send us anything. val irrelevantTX = TransactionType.General.Builder(DUMMY_NOTARY).apply { - Cash().generateIssue(this, 100.DOLLARS `issued by` MEGA_CORP.ref(1), BOB_KEY.public, DUMMY_NOTARY) + Cash().generateIssue(this, 100.DOLLARS `issued by` MEGA_CORP.ref(1), BOB, DUMMY_NOTARY) signWith(MEGA_CORP_KEY) signWith(DUMMY_NOTARY_KEY) }.toSignedTransaction() @@ -128,13 +129,14 @@ class VaultWithCashTest { @Test fun `issue and attempt double spend`() { val freshKey = services.keyManagementService.freshKey() + val freshPublicKey = freshKey.public database.transaction { // A tx that sends us money. services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 10, 10, Random(0L), issuedBy = MEGA_CORP.ref(1), issuerKey = MEGA_CORP_KEY, - ownedBy = freshKey.public) + ownedBy = AnonymousParty(freshPublicKey)) println("Cash balance: ${vault.cashBalances[USD]}") assertThat(vault.unconsumedStates()).hasSize(10) @@ -149,7 +151,7 @@ class VaultWithCashTest { try { val txn1 = TransactionType.General.Builder(DUMMY_NOTARY).apply { - vault.generateSpend(this, 60.DOLLARS, BOB_PUBKEY) + vault.generateSpend(this, 60.DOLLARS, BOB) signWith(freshKey) signWith(DUMMY_NOTARY_KEY) }.toSignedTransaction() @@ -181,7 +183,7 @@ class VaultWithCashTest { try { val txn2 = TransactionType.General.Builder(DUMMY_NOTARY).apply { - vault.generateSpend(this, 80.DOLLARS, BOB_PUBKEY) + vault.generateSpend(this, 80.DOLLARS, BOB) signWith(freshKey) signWith(DUMMY_NOTARY_KEY) }.toSignedTransaction() @@ -219,12 +221,14 @@ class VaultWithCashTest { fun `branching LinearStates fails to verify`() { database.transaction { val freshKey = services.keyManagementService.freshKey() + val freshPublicKey = freshKey.public + val freshIdentity = AnonymousParty(freshPublicKey) val linearId = UniqueIdentifier() // Issue a linear state val dummyIssue = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply { - addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshKey.public))) - addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshKey.public))) + addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity))) + addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity))) signWith(freshKey) signWith(DUMMY_NOTARY_KEY) }.toSignedTransaction() @@ -239,12 +243,14 @@ class VaultWithCashTest { fun `sequencing LinearStates works`() { database.transaction { val freshKey = services.keyManagementService.freshKey() + val freshPublicKey = freshKey.public + val freshIdentity = AnonymousParty(freshPublicKey) val linearId = UniqueIdentifier() // Issue a linear state val dummyIssue = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply { - addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshKey.public))) + addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity))) signWith(freshKey) signWith(DUMMY_NOTARY_KEY) }.toSignedTransaction() @@ -256,7 +262,7 @@ class VaultWithCashTest { // Move the same state val dummyMove = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply { - addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshKey.public))) + addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity))) addInputState(dummyIssue.tx.outRef(0)) signWith(DUMMY_NOTARY_KEY) }.toSignedTransaction() @@ -272,8 +278,9 @@ class VaultWithCashTest { fun `spending cash in vault of mixed state types works`() { val freshKey = services.keyManagementService.freshKey() + val freshPublicKey = freshKey.public database.transaction { - services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L), ownedBy = freshKey.public) + services.fillWithSomeTestCash(100.DOLLARS, DUMMY_NOTARY, 3, 3, Random(0L), ownedBy = AnonymousParty(freshPublicKey)) services.fillWithSomeTestCash(100.SWISS_FRANCS, DUMMY_NOTARY, 2, 2, Random(0L)) services.fillWithSomeTestCash(100.POUNDS, DUMMY_NOTARY, 1, 1, Random(0L)) val cash = vault.unconsumedStates() @@ -287,7 +294,7 @@ class VaultWithCashTest { database.transaction { // A tx that spends our money. val spendTX = TransactionType.General.Builder(DUMMY_NOTARY).apply { - vault.generateSpend(this, 80.DOLLARS, BOB_PUBKEY) + vault.generateSpend(this, 80.DOLLARS, BOB) signWith(freshKey) signWith(DUMMY_NOTARY_KEY) }.toSignedTransaction() @@ -305,6 +312,8 @@ class VaultWithCashTest { fun `consuming multiple contract state types in same transaction`() { val freshKey = services.keyManagementService.freshKey() + val freshPublicKey = freshKey.public + val freshIdentity = AnonymousParty(freshPublicKey) database.transaction { services.fillWithSomeTestDeals(listOf("123", "456", "789")) @@ -317,8 +326,8 @@ class VaultWithCashTest { // Create a txn consuming different contract types val dummyMove = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply { - addOutputState(DummyLinearContract.State(participants = listOf(freshKey.public))) - addOutputState(DummyDealContract.State(ref = "999", participants = listOf(freshKey.public))) + addOutputState(DummyLinearContract.State(participants = listOf(freshIdentity))) + addOutputState(DummyDealContract.State(ref = "999", participants = listOf(freshIdentity))) addInputState(linearStates.first()) addInputState(deals.first()) signWith(DUMMY_NOTARY_KEY) diff --git a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/AttachmentDemo.kt b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/AttachmentDemo.kt index 4ca8f0e9ee..745d83e4cf 100644 --- a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/AttachmentDemo.kt +++ b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/AttachmentDemo.kt @@ -13,6 +13,7 @@ import net.corda.core.crypto.SecureHash import net.corda.core.flows.FlowLogic import net.corda.core.flows.StartableByRPC import net.corda.core.getOrThrow +import net.corda.core.identity.AbstractParty import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.startTrackedFlow import net.corda.core.sizedInputStreamAndHash @@ -179,6 +180,6 @@ class AttachmentContract : Contract { data class State(val hash: SecureHash.SHA256) : ContractState { override val contract: Contract = AttachmentContract() - override val participants: List = emptyList() + override val participants: List = emptyList() } } diff --git a/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt b/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt index d0fabb3c87..cf2eaea98c 100644 --- a/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt +++ b/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt @@ -70,7 +70,7 @@ class IRSDemoTest : IntegrationTestCategory { val vaultUpdates = proxy.vaultAndUpdates().second val fixingDates = vaultUpdates.map { update -> - val irsStates = update.produced.map { it.state.data }.filterIsInstance>() + val irsStates = update.produced.map { it.state.data }.filterIsInstance() irsStates.mapNotNull { it.calculation.nextFixingDate() }.max() }.cache().toBlocking() diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/api/InterestRateSwapAPI.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/api/InterestRateSwapAPI.kt index 4c6bc8b864..8f09afaebf 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/api/InterestRateSwapAPI.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/api/InterestRateSwapAPI.kt @@ -40,22 +40,22 @@ class InterestRateSwapAPI(val rpc: CordaRPCOps) { private val logger = loggerFor() - private fun generateDealLink(deal: InterestRateSwap.State<*>) = "/api/irs/deals/" + deal.common.tradeID + private fun generateDealLink(deal: InterestRateSwap.State) = "/api/irs/deals/" + deal.common.tradeID - private fun getDealByRef(ref: String): InterestRateSwap.State<*>? { + private fun getDealByRef(ref: String): InterestRateSwap.State? { val (vault, vaultUpdates) = rpc.vaultAndUpdates() vaultUpdates.notUsed() - val states = vault.filterStatesOfType>().filter { it.state.data.ref == ref } + val states = vault.filterStatesOfType().filter { it.state.data.ref == ref } return if (states.isEmpty()) null else { val deals = states.map { it.state.data } return if (deals.isEmpty()) null else deals[0] } } - private fun getAllDeals(): Array> { + private fun getAllDeals(): Array { val (vault, vaultUpdates) = rpc.vaultAndUpdates() vaultUpdates.notUsed() - val states = vault.filterStatesOfType>() + val states = vault.filterStatesOfType() val swaps = states.map { it.state.data }.toTypedArray() return swaps } @@ -63,14 +63,14 @@ class InterestRateSwapAPI(val rpc: CordaRPCOps) { @GET @Path("deals") @Produces(MediaType.APPLICATION_JSON) - fun fetchDeals(): Array> = getAllDeals() + fun fetchDeals(): Array = getAllDeals() @POST @Path("deals") @Consumes(MediaType.APPLICATION_JSON) - fun storeDeal(newDeal: InterestRateSwap.State): Response { + fun storeDeal(newDeal: InterestRateSwap.State): Response { return try { - rpc.startFlow(AutoOfferFlow::Requester, newDeal.toAnonymous()).returnValue.getOrThrow() + rpc.startFlow(AutoOfferFlow::Requester, newDeal).returnValue.getOrThrow() Response.created(URI.create(generateDealLink(newDeal))).build() } catch (ex: Throwable) { logger.info("Exception when creating deal: $ex") diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/contract/IRS.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/contract/IRS.kt index 2379573e8a..4c21148852 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/contract/IRS.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/contract/IRS.kt @@ -2,7 +2,8 @@ package net.corda.irs.contract import net.corda.core.contracts.* import net.corda.core.contracts.clauses.* -import net.corda.core.crypto.* +import net.corda.core.crypto.SecureHash +import net.corda.core.crypto.containsAny import net.corda.core.flows.FlowLogicRefFactory import net.corda.core.identity.AbstractParty import net.corda.core.identity.AnonymousParty @@ -307,8 +308,8 @@ class InterestRateSwap : Contract { } @CordaSerializable - open class FixedLeg

( - var fixedRatePayer: P, + open class FixedLeg( + var fixedRatePayer: AbstractParty, notional: Amount, paymentFrequency: Frequency, effectiveDate: LocalDate, @@ -335,7 +336,7 @@ class InterestRateSwap : Contract { if (other?.javaClass != javaClass) return false if (!super.equals(other)) return false - other as FixedLeg<*> + other as FixedLeg if (fixedRatePayer != other.fixedRatePayer) return false if (fixedRate != other.fixedRate) return false @@ -347,7 +348,7 @@ class InterestRateSwap : Contract { override fun hashCode() = super.hashCode() + 31 * Objects.hash(fixedRatePayer, fixedRate, rollConvention) // Can't autogenerate as not a data class :-( - fun copy(fixedRatePayer: P = this.fixedRatePayer, + fun copy(fixedRatePayer: AbstractParty = this.fixedRatePayer, notional: Amount = this.notional, paymentFrequency: Frequency = this.paymentFrequency, effectiveDate: LocalDate = this.effectiveDate, @@ -365,17 +366,11 @@ class InterestRateSwap : Contract { fixedRatePayer, notional, paymentFrequency, effectiveDate, effectiveDateAdjustment, terminationDate, terminationDateAdjustment, dayCountBasisDay, dayCountBasisYear, dayInMonth, paymentRule, paymentDelay, paymentCalendar, interestPeriodAdjustment, fixedRate, rollConvention) - - fun toAnonymous(): FixedLeg { - return FixedLeg(fixedRatePayer.toAnonymous(), notional, paymentFrequency, effectiveDate, effectiveDateAdjustment, terminationDate, terminationDateAdjustment, - dayCountBasisDay, dayCountBasisYear, dayInMonth, paymentRule, paymentDelay, paymentCalendar, interestPeriodAdjustment, - fixedRate, rollConvention) - } } @CordaSerializable - open class FloatingLeg

( - var floatingRatePayer: P, + open class FloatingLeg( + var floatingRatePayer: AbstractParty, notional: Amount, paymentFrequency: Frequency, effectiveDate: LocalDate, @@ -411,7 +406,7 @@ class InterestRateSwap : Contract { if (other?.javaClass != javaClass) return false if (!super.equals(other)) return false - other as FloatingLeg<*> + other as FloatingLeg if (floatingRatePayer != other.floatingRatePayer) return false if (rollConvention != other.rollConvention) return false @@ -433,7 +428,7 @@ class InterestRateSwap : Contract { index, indexSource, indexTenor) - fun copy(floatingRatePayer: P = this.floatingRatePayer, + fun copy(floatingRatePayer: AbstractParty = this.floatingRatePayer, notional: Amount = this.notional, paymentFrequency: Frequency = this.paymentFrequency, effectiveDate: LocalDate = this.effectiveDate, @@ -462,13 +457,6 @@ class InterestRateSwap : Contract { paymentRule, paymentDelay, paymentCalendar, interestPeriodAdjustment, rollConvention, fixingRollConvention, resetDayInMonth, fixingPeriod, resetRule, fixingsPerPayment, fixingCalendar, index, indexSource, indexTenor) - - fun toAnonymous(): FloatingLeg { - return FloatingLeg(floatingRatePayer.toAnonymous(), notional, paymentFrequency, effectiveDate, effectiveDateAdjustment, terminationDate, terminationDateAdjustment, - dayCountBasisDay, dayCountBasisYear, dayInMonth, paymentRule, paymentDelay, paymentCalendar, interestPeriodAdjustment, - rollConvention, fixingRollConvention, resetDayInMonth, fixingPeriodOffset, resetRule, fixingsPerPayment, - fixingCalendar, index, indexSource, indexTenor) - } } override fun verify(tx: TransactionForContract) = verifyClause(tx, AllOf(Clauses.Timestamped(), Clauses.Group()), tx.commands.select()) @@ -478,7 +466,7 @@ class InterestRateSwap : Contract { * Common superclass for IRS contract clauses, which defines behaviour on match/no-match, and provides * helper functions for the clauses. */ - abstract class AbstractIRSClause : Clause, Commands, UniqueIdentifier>() { + abstract class AbstractIRSClause : Clause() { // These functions may make more sense to use for basket types, but for now let's leave them here fun checkLegDates(legs: List) { requireThat { @@ -494,7 +482,7 @@ class InterestRateSwap : Contract { "The notional for all legs must be the same" using legs.all { it.notional == legs[0].notional } } for (leg: CommonLeg in legs) { - if (leg is FixedLeg<*>) { + if (leg is FixedLeg) { requireThat { // TODO: Confirm: would someone really enter a swap with a negative fixed rate? "Fixed leg rate must be positive" using leg.fixedRate.isPositive() @@ -520,9 +508,9 @@ class InterestRateSwap : Contract { } } - class Group : GroupClauseVerifier, Commands, UniqueIdentifier>(AnyOf(Agree(), Fix(), Pay(), Mature())) { + class Group : GroupClauseVerifier(AnyOf(Agree(), Fix(), Pay(), Mature())) { // Group by Trade ID for in / out states - override fun groupStates(tx: TransactionForContract): List, UniqueIdentifier>> { + override fun groupStates(tx: TransactionForContract): List> { return tx.groupStates { state -> state.linearId } } } @@ -543,12 +531,12 @@ class InterestRateSwap : Contract { override val requiredCommands: Set> = setOf(Commands.Agree::class.java) override fun verify(tx: TransactionForContract, - inputs: List>, - outputs: List>, + inputs: List, + outputs: List, commands: List>, groupingKey: UniqueIdentifier?): Set { val command = tx.commands.requireSingleCommand() - val irs = outputs.filterIsInstance>().single() + val irs = outputs.filterIsInstance().single() requireThat { "There are no in states for an agreement" using inputs.isEmpty() "There are events in the fix schedule" using (irs.calculation.fixedLegPaymentSchedule.isNotEmpty()) @@ -579,13 +567,13 @@ class InterestRateSwap : Contract { override val requiredCommands: Set> = setOf(Commands.Refix::class.java) override fun verify(tx: TransactionForContract, - inputs: List>, - outputs: List>, + inputs: List, + outputs: List, commands: List>, groupingKey: UniqueIdentifier?): Set { val command = tx.commands.requireSingleCommand() - val irs = outputs.filterIsInstance>().single() - val prevIrs = inputs.filterIsInstance>().single() + val irs = outputs.filterIsInstance().single() + val prevIrs = inputs.filterIsInstance().single() val paymentDifferences = getFloatingLegPaymentsDifferences(prevIrs.calculation.floatingLegPaymentSchedule, irs.calculation.floatingLegPaymentSchedule) // Having both of these tests are "redundant" as far as verify() goes, however, by performing both @@ -624,8 +612,8 @@ class InterestRateSwap : Contract { override val requiredCommands: Set> = setOf(Commands.Pay::class.java) override fun verify(tx: TransactionForContract, - inputs: List>, - outputs: List>, + inputs: List, + outputs: List, commands: List>, groupingKey: UniqueIdentifier?): Set { val command = tx.commands.requireSingleCommand() @@ -640,12 +628,12 @@ class InterestRateSwap : Contract { override val requiredCommands: Set> = setOf(Commands.Mature::class.java) override fun verify(tx: TransactionForContract, - inputs: List>, - outputs: List>, + inputs: List, + outputs: List, commands: List>, groupingKey: UniqueIdentifier?): Set { val command = tx.commands.requireSingleCommand() - val irs = inputs.filterIsInstance>().single() + val irs = inputs.filterIsInstance().single() requireThat { "No more fixings to be applied" using (irs.calculation.nextFixingDate() == null) "The irs is fully consumed and there is no id matched output state" using outputs.isEmpty() @@ -667,9 +655,9 @@ class InterestRateSwap : Contract { /** * The state class contains the 4 major data classes. */ - data class State

( - val fixedLeg: FixedLeg

, - val floatingLeg: FloatingLeg

, + data class State( + val fixedLeg: FixedLeg, + val floatingLeg: FloatingLeg, val calculation: Calculation, val common: Common, override val linearId: UniqueIdentifier = UniqueIdentifier(common.tradeID) @@ -682,15 +670,15 @@ class InterestRateSwap : Contract { override val ref = common.tradeID - override val participants: List - get() = parties.map { it.owningKey } + override val participants: List + get() = parties override fun isRelevant(ourKeys: Set): Boolean { return fixedLeg.fixedRatePayer.owningKey.containsAny(ourKeys) || floatingLeg.floatingRatePayer.owningKey.containsAny(ourKeys) } - override val parties: List - get() = listOf(fixedLeg.fixedRatePayer.toAnonymous(), floatingLeg.floatingRatePayer.toAnonymous()) + override val parties: List + get() = listOf(fixedLeg.fixedRatePayer, floatingLeg.floatingRatePayer) override fun nextScheduledActivity(thisStateRef: StateRef, flowLogicRefFactory: FlowLogicRefFactory): ScheduledActivity? { val nextFixingOf = nextFixingOf() ?: return null @@ -700,10 +688,10 @@ class InterestRateSwap : Contract { return ScheduledActivity(flowLogicRefFactory.create(FixingFlow.FixingRoleDecider::class.java, thisStateRef), instant) } - override fun generateAgreement(notary: Party): TransactionBuilder = InterestRateSwap().generateAgreement(floatingLeg.toAnonymous(), fixedLeg.toAnonymous(), calculation, common, notary) + override fun generateAgreement(notary: Party): TransactionBuilder = InterestRateSwap().generateAgreement(floatingLeg, fixedLeg, calculation, common, notary) override fun generateFix(ptx: TransactionBuilder, oldState: StateAndRef<*>, fix: Fix) { - InterestRateSwap().generateFix(ptx, StateAndRef(TransactionState(this.toAnonymous(), oldState.state.notary), oldState.ref), fix) + InterestRateSwap().generateFix(ptx, StateAndRef(TransactionState(this, oldState.state.notary), oldState.ref), fix) } override fun nextFixingOf(): FixOf? { @@ -737,22 +725,13 @@ class InterestRateSwap : Contract { * Just makes printing it out a bit better for those who don't have 80000 column wide monitors. */ fun prettyPrint() = toString().replace(",", "\n") - - fun toAnonymous(): State { - return if (this.fixedLeg.fixedRatePayer is AnonymousParty) { - @Suppress("UNCHECKED_CAST") - this as State - } else { - State(fixedLeg.toAnonymous(), floatingLeg.toAnonymous(), calculation, common, linearId) - } - } } /** * This generates the agreement state and also the schedules from the initial data. * Note: The day count, interest rate calculation etc are not finished yet, but they are demonstrable. */ - fun generateAgreement(floatingLeg: FloatingLeg, fixedLeg: FixedLeg, calculation: Calculation, + fun generateAgreement(floatingLeg: FloatingLeg, fixedLeg: FixedLeg, calculation: Calculation, common: Common, notary: Party): TransactionBuilder { val fixedLegPaymentSchedule = LinkedHashMap() @@ -816,7 +795,7 @@ class InterestRateSwap : Contract { } } - fun generateFix(tx: TransactionBuilder, irs: StateAndRef>, fixing: Fix) { + fun generateFix(tx: TransactionBuilder, irs: StateAndRef, fixing: Fix) { tx.addInputState(irs) val fixedRate = FixedRate(RatioUnit(fixing.value)) tx.addOutputState( diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/contract/IRSExport.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/contract/IRSExport.kt index 68887f88d4..3caa9e21c2 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/contract/IRSExport.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/contract/IRSExport.kt @@ -1,6 +1,6 @@ package net.corda.irs.contract -fun InterestRateSwap.State<*>.exportIRSToCSV(): String = +fun InterestRateSwap.State.exportIRSToCSV(): String = "Fixed Leg\n" + FixedRatePaymentEvent.CSVHeader + "\n" + this.calculation.fixedLegPaymentSchedule.toSortedMap().values.map { it.asCSV() }.joinToString("\n") + "\n" + "Floating Leg\n" + FloatingRatePaymentEvent.CSVHeader + "\n" + diff --git a/samples/irs-demo/src/main/kotlin/net/corda/simulation/IRSSimulation.kt b/samples/irs-demo/src/main/kotlin/net/corda/simulation/IRSSimulation.kt index 7ae55b7a83..b541499d64 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/simulation/IRSSimulation.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/simulation/IRSSimulation.kt @@ -79,9 +79,9 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten return future } - private fun loadLinearHeads(node: SimulatedNode): Map>> { + private fun loadLinearHeads(node: SimulatedNode): Map> { return node.database.transaction { - node.services.vaultService.linearHeadsOfType>() + node.services.vaultService.linearHeadsOfType() } } @@ -90,8 +90,8 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten val node1: SimulatedNode = banks[i] val node2: SimulatedNode = banks[j] - val swaps: Map>> = loadLinearHeads(node1) - val theDealRef: StateAndRef> = swaps.values.single() + val swaps: Map> = loadLinearHeads(node1) + val theDealRef: StateAndRef = swaps.values.single() // Do we have any more days left in this deal's lifetime? If not, return. val nextFixingDate = theDealRef.state.data.calculation.nextFixingDate() ?: return null @@ -121,9 +121,9 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten // We load the IRS afresh each time because the leg parts of the structure aren't data classes so they don't // have the convenient copy() method that'd let us make small adjustments. Instead they're partly mutable. // TODO: We should revisit this in post-Excalibur cleanup and fix, e.g. by introducing an interface. - val irs = om.readValue>(javaClass.classLoader.getResource("simulation/trade.json")) - irs.fixedLeg.fixedRatePayer = node1.info.legalIdentity.toAnonymous() - irs.floatingLeg.floatingRatePayer = node2.info.legalIdentity.toAnonymous() + val irs = om.readValue(javaClass.classLoader.getResource("simulation/trade.json")) + irs.fixedLeg.fixedRatePayer = node1.info.legalIdentity + irs.floatingLeg.floatingRatePayer = node2.info.legalIdentity @InitiatingFlow class StartDealFlow(val otherParty: Party, diff --git a/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/IRSTests.kt b/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/IRSTests.kt index 205f2d707d..6ca77b8058 100644 --- a/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/IRSTests.kt +++ b/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/IRSTests.kt @@ -16,12 +16,12 @@ import java.time.LocalDate import java.util.* import kotlin.test.assertEquals -fun createDummyIRS(irsSelect: Int): InterestRateSwap.State { +fun createDummyIRS(irsSelect: Int): InterestRateSwap.State { return when (irsSelect) { 1 -> { val fixedLeg = InterestRateSwap.FixedLeg( - fixedRatePayer = MEGA_CORP.toAnonymous(), + fixedRatePayer = MEGA_CORP, notional = 15900000.DOLLARS, paymentFrequency = Frequency.SemiAnnual, effectiveDate = LocalDate.of(2016, 3, 10), @@ -40,7 +40,7 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State { ) val floatingLeg = InterestRateSwap.FloatingLeg( - floatingRatePayer = MINI_CORP.toAnonymous(), + floatingRatePayer = MINI_CORP, notional = 15900000.DOLLARS, paymentFrequency = Frequency.Quarterly, effectiveDate = LocalDate.of(2016, 3, 10), @@ -111,7 +111,7 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State { // I did a mock up start date 10/03/2015 – 10/03/2025 so you have 5 cashflows on float side that have been preset the rest are unknown val fixedLeg = InterestRateSwap.FixedLeg( - fixedRatePayer = MEGA_CORP.toAnonymous(), + fixedRatePayer = MEGA_CORP, notional = 25000000.DOLLARS, paymentFrequency = Frequency.SemiAnnual, effectiveDate = LocalDate.of(2015, 3, 10), @@ -130,7 +130,7 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State { ) val floatingLeg = InterestRateSwap.FloatingLeg( - floatingRatePayer = MINI_CORP.toAnonymous(), + floatingRatePayer = MINI_CORP, notional = 25000000.DOLLARS, paymentFrequency = Frequency.Quarterly, effectiveDate = LocalDate.of(2015, 3, 10), @@ -246,8 +246,8 @@ class IRSTests { /** * Utility so I don't have to keep typing this. */ - fun singleIRS(irsSelector: Int = 1): InterestRateSwap.State { - return generateIRSTxn(irsSelector).tx.outputs.map { it.data }.filterIsInstance>().single() + fun singleIRS(irsSelector: Int = 1): InterestRateSwap.State { + return generateIRSTxn(irsSelector).tx.outputs.map { it.data }.filterIsInstance().single() } /** @@ -301,7 +301,7 @@ class IRSTests { var previousTXN = generateIRSTxn(1) previousTXN.toLedgerTransaction(services).verify() services.recordTransactions(previousTXN) - fun currentIRS() = previousTXN.tx.outputs.map { it.data }.filterIsInstance>().single() + fun currentIRS() = previousTXN.tx.outputs.map { it.data }.filterIsInstance().single() while (true) { val nextFix: FixOf = currentIRS().nextFixingOf() ?: break @@ -381,7 +381,7 @@ class IRSTests { transaction("Fix") { input("irs post agreement") - val postAgreement = "irs post agreement".output>() + val postAgreement = "irs post agreement".output() output("irs post first fixing") { postAgreement.copy( postAgreement.fixedLeg, @@ -688,7 +688,7 @@ class IRSTests { transaction("Fix") { input("irs post agreement1") input("irs post agreement2") - val postAgreement1 = "irs post agreement1".output>() + val postAgreement1 = "irs post agreement1".output() output("irs post first fixing1") { postAgreement1.copy( postAgreement1.fixedLeg, @@ -697,7 +697,7 @@ class IRSTests { postAgreement1.common.copy(tradeID = "t1") ) } - val postAgreement2 = "irs post agreement2".output>() + val postAgreement2 = "irs post agreement2".output() output("irs post first fixing2") { postAgreement2.copy( postAgreement2.fixedLeg, diff --git a/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/NodeInterestRatesTest.kt b/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/NodeInterestRatesTest.kt index 1cc89d4376..8a56a1eee0 100644 --- a/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/NodeInterestRatesTest.kt +++ b/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/NodeInterestRatesTest.kt @@ -13,6 +13,7 @@ import net.corda.core.crypto.generateKeyPair import net.corda.core.getOrThrow import net.corda.core.node.services.ServiceInfo import net.corda.core.transactions.TransactionBuilder +import net.corda.core.utilities.ALICE import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.LogHelper import net.corda.core.utilities.ProgressTracker @@ -241,5 +242,5 @@ class NodeInterestRatesTest { } } - private fun makeTX() = TransactionType.General.Builder(DUMMY_NOTARY).withItems(1000.DOLLARS.CASH `issued by` DUMMY_CASH_ISSUER `owned by` ALICE_PUBKEY `with notary` DUMMY_NOTARY) + private fun makeTX() = TransactionType.General.Builder(DUMMY_NOTARY).withItems(1000.DOLLARS.CASH `issued by` DUMMY_CASH_ISSUER `owned by` ALICE `with notary` DUMMY_NOTARY) } diff --git a/samples/raft-notary-demo/src/main/kotlin/net/corda/notarydemo/flows/DummyIssueAndMove.kt b/samples/raft-notary-demo/src/main/kotlin/net/corda/notarydemo/flows/DummyIssueAndMove.kt index 11b4fd12b3..5b14b272de 100644 --- a/samples/raft-notary-demo/src/main/kotlin/net/corda/notarydemo/flows/DummyIssueAndMove.kt +++ b/samples/raft-notary-demo/src/main/kotlin/net/corda/notarydemo/flows/DummyIssueAndMove.kt @@ -20,9 +20,8 @@ class DummyIssueAndMove(private val notary: Party, private val counterpartyNode: } serviceHub.recordTransactions(issueTx.toSignedTransaction()) // Move ownership of the asset to the counterparty - val counterPartyKey = counterpartyNode.owningKey val asset = issueTx.toWireTransaction().outRef(0) - val moveTx = DummyContract.move(asset, counterPartyKey).apply { + val moveTx = DummyContract.move(asset, counterpartyNode).apply { signWith(myKeyPair) } // We don't check signatures because we know that the notary's signature is missing diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/IRSState.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/IRSState.kt index 05f4b8075d..35898c508d 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/IRSState.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/IRSState.kt @@ -4,9 +4,9 @@ import net.corda.core.contracts.Command import net.corda.core.contracts.DealState import net.corda.core.contracts.TransactionType import net.corda.core.contracts.UniqueIdentifier -import net.corda.core.identity.AnonymousParty -import net.corda.core.identity.Party import net.corda.core.crypto.keys +import net.corda.core.identity.AbstractParty +import net.corda.core.identity.Party import net.corda.core.transactions.TransactionBuilder import java.security.PublicKey @@ -16,12 +16,12 @@ import java.security.PublicKey * TODO: Merge with the existing demo IRS code. */ data class IRSState(val swap: SwapData, - val buyer: AnonymousParty, - val seller: AnonymousParty, + val buyer: AbstractParty, + val seller: AbstractParty, override val contract: OGTrade, override val linearId: UniqueIdentifier = UniqueIdentifier(swap.id.first + swap.id.second)) : DealState { override val ref: String = linearId.externalId!! // Same as the constructor for UniqueIdentified - override val parties: List get() = listOf(buyer, seller) + override val parties: List get() = listOf(buyer, seller) override fun isRelevant(ourKeys: Set): Boolean { return parties.flatMap { it.owningKey.keys }.intersect(ourKeys).isNotEmpty() @@ -32,6 +32,6 @@ data class IRSState(val swap: SwapData, return TransactionType.General.Builder(notary).withItems(state, Command(OGTrade.Commands.Agree(), parties.map { it.owningKey })) } - override val participants: List - get() = parties.map { it.owningKey } + override val participants: List + get() = parties } diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/OGTrade.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/OGTrade.kt index 4d036a92a0..97cc7dc43b 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/OGTrade.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/OGTrade.kt @@ -45,7 +45,7 @@ data class OGTrade(override val legalContractReference: SecureHash = SecureHash. require(inputs.size == 0) { "Inputs must be empty" } require(outputs.size == 1) { "" } require(outputs[0].buyer != outputs[0].seller) - require(outputs[0].parties.map { it.owningKey }.containsAll(outputs[0].participants)) + require(outputs[0].parties.containsAll(outputs[0].participants)) require(outputs[0].parties.containsAll(listOf(outputs[0].buyer, outputs[0].seller))) require(outputs[0].swap.startDate.isBefore(outputs[0].swap.endDate)) require(outputs[0].swap.notional > BigDecimal(0)) diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/PortfolioState.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/PortfolioState.kt index 6677ebd882..083fe655bd 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/PortfolioState.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/PortfolioState.kt @@ -1,10 +1,10 @@ package net.corda.vega.contracts import net.corda.core.contracts.* -import net.corda.core.identity.AnonymousParty -import net.corda.core.identity.Party import net.corda.core.crypto.keys import net.corda.core.flows.FlowLogicRefFactory +import net.corda.core.identity.AbstractParty +import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.transactions.TransactionBuilder import net.corda.vega.flows.SimmRevaluation @@ -19,7 +19,7 @@ import java.time.temporal.ChronoUnit */ data class PortfolioState(val portfolio: List, override val contract: PortfolioSwap, - private val _parties: Pair, + private val _parties: Pair, val valuationDate: LocalDate, val valuation: PortfolioValuation? = null, override val linearId: UniqueIdentifier = UniqueIdentifier()) @@ -27,12 +27,12 @@ data class PortfolioState(val portfolio: List, @CordaSerializable data class Update(val portfolio: List? = null, val valuation: PortfolioValuation? = null) - override val parties: List get() = _parties.toList() + override val parties: List get() = _parties.toList() override val ref: String = linearId.toString() - val valuer: AnonymousParty get() = parties[0] + val valuer: AbstractParty get() = parties[0] - override val participants: List - get() = parties.map { it.owningKey } + override val participants: List + get() = parties override fun nextScheduledActivity(thisStateRef: StateRef, flowLogicRefFactory: FlowLogicRefFactory): ScheduledActivity { val flow = flowLogicRefFactory.create(SimmRevaluation.Initiator::class.java, thisStateRef, LocalDate.now()) diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/PortfolioSwap.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/PortfolioSwap.kt index 809b426e84..4dad44ad41 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/PortfolioSwap.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/PortfolioSwap.kt @@ -71,7 +71,7 @@ data class PortfolioSwap(override val legalContractReference: SecureHash = Secur "there are no inputs" using (inputs.size == 0) "there is one output" using (outputs.size == 1) "valuer must be a party" using (outputs[0].parties.contains(outputs[0].valuer)) - "all participants must be parties" using (outputs[0].parties.map { it.owningKey }.containsAll(outputs[0].participants)) + "all participants must be parties" using (outputs[0].parties.containsAll(outputs[0].participants)) } return setOf(command.value) diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/IRSTradeFlow.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/IRSTradeFlow.kt index d46ff74a4b..11a8363f92 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/IRSTradeFlow.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/IRSTradeFlow.kt @@ -1,10 +1,10 @@ package net.corda.vega.flows import co.paralleluniverse.fibers.Suspendable -import net.corda.core.identity.Party import net.corda.core.flows.FlowLogic import net.corda.core.flows.InitiatingFlow import net.corda.core.flows.StartableByRPC +import net.corda.core.identity.Party import net.corda.core.node.PluginServiceHub import net.corda.core.serialization.CordaSerializable import net.corda.core.transactions.SignedTransaction @@ -38,7 +38,7 @@ object IRSTradeFlow { } else { Pair(otherParty, myIdentity) } - val offer = IRSState(swap, buyer.toAnonymous(), seller.toAnonymous(), OGTrade()) + val offer = IRSState(swap, buyer, seller, OGTrade()) logger.info("Handshake finished, sending IRS trade offer message") val otherPartyAgreeFlag = sendAndReceive(otherParty, OfferMessage(notary, offer)).unwrap { it } diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmFlow.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmFlow.kt index d4b4342b0a..94061ba0d5 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmFlow.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmFlow.kt @@ -10,11 +10,11 @@ import com.opengamma.strata.pricer.rate.ImmutableRatesProvider import com.opengamma.strata.pricer.swap.DiscountingSwapProductPricer import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.StateRef -import net.corda.core.identity.AnonymousParty -import net.corda.core.identity.Party import net.corda.core.flows.FlowLogic import net.corda.core.flows.InitiatingFlow import net.corda.core.flows.StartableByRPC +import net.corda.core.identity.AnonymousParty +import net.corda.core.identity.Party import net.corda.core.node.PluginServiceHub import net.corda.core.node.services.dealsWith import net.corda.core.serialization.CordaSerializable @@ -85,7 +85,7 @@ object SimmFlow { @Suspendable private fun agreePortfolio(portfolio: Portfolio) { logger.info("Agreeing portfolio") - val parties = Pair(myIdentity.toAnonymous(), otherParty.toAnonymous()) + val parties = Pair(myIdentity, otherParty) val portfolioState = PortfolioState(portfolio.refs, PortfolioSwap(), parties, valuationDate) send(otherParty, OfferMessage(notary, portfolioState, existing?.ref, valuationDate)) @@ -219,13 +219,6 @@ object SimmFlow { return receive(replyToParty).unwrap { it } } - @Suspendable - private fun agreeValuation(portfolio: Portfolio, asOf: LocalDate, valuer: AnonymousParty): PortfolioValuation { - val valuerParty = serviceHub.identityService.partyFromAnonymous(valuer) - require(valuerParty != null) - return agreeValuation(portfolio, asOf, valuerParty!!) - } - /** * So this is the crux of the Simm Agreement flow * It needs to do several things - which are mainly defined by the analytics engine we are using - which in this @@ -326,7 +319,7 @@ object SimmFlow { @Suspendable private fun updateValuation(stateRef: StateAndRef) { val portfolio = stateRef.state.data.portfolio.toStateAndRef(serviceHub).toPortfolio() - val valuer = stateRef.state.data.valuer + val valuer = serviceHub.identityService.partyFromAnonymous(stateRef.state.data.valuer) ?: throw IllegalStateException("Unknown valuer party ${stateRef.state.data.valuer}") val valuation = agreeValuation(portfolio, offer.valuationDate, valuer) subFlow(object : StateRevisionFlow.Receiver(replyToParty) { override fun verifyProposal(proposal: Proposal) { diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmRevaluation.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmRevaluation.kt index d6e932c6e5..e687fd710f 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmRevaluation.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmRevaluation.kt @@ -21,7 +21,7 @@ object SimmRevaluation { override fun call(): Unit { val stateAndRef = serviceHub.vaultService.linearHeadsOfType().values.first { it.ref == curStateRef } val curState = stateAndRef.state.data - val myIdentity = serviceHub.myInfo.legalIdentity.toAnonymous() + val myIdentity = serviceHub.myInfo.legalIdentity if (myIdentity == curState.parties[0]) { val otherParty = serviceHub.identityService.partyFromAnonymous(curState.parties[1]) require(otherParty != null) { "Other party must be known by this node" } diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/StateRevisionFlow.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/StateRevisionFlow.kt index f4e3108fcf..e1f5a9c9c3 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/StateRevisionFlow.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/StateRevisionFlow.kt @@ -1,6 +1,7 @@ package net.corda.vega.flows import net.corda.core.contracts.StateAndRef +import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.seconds import net.corda.core.transactions.SignedTransaction @@ -16,7 +17,7 @@ import java.security.PublicKey object StateRevisionFlow { class Requester(curStateRef: StateAndRef>, updatedData: T) : AbstractStateReplacementFlow.Instigator, RevisionedState, T>(curStateRef, updatedData) { - override fun assembleTx(): Pair> { + override fun assembleTx(): Pair> { val state = originalState.state.data val tx = state.generateRevision(originalState.state.notary, originalState, modification) tx.setTime(serviceHub.clock.instant(), 30.seconds) diff --git a/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/SellerFlow.kt b/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/SellerFlow.kt index 9222a27a9c..e90ca1c4fa 100644 --- a/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/SellerFlow.kt +++ b/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/SellerFlow.kt @@ -11,6 +11,7 @@ import net.corda.core.days import net.corda.core.flows.FlowLogic import net.corda.core.flows.InitiatingFlow import net.corda.core.flows.StartableByRPC +import net.corda.core.identity.AbstractParty import net.corda.core.node.NodeInfo import net.corda.core.seconds import net.corda.core.transactions.SignedTransaction @@ -50,7 +51,7 @@ class SellerFlow(val otherParty: Party, val notary: NodeInfo = serviceHub.networkMapCache.notaryNodes[0] val cpOwnerKey = serviceHub.legalIdentityKey - val commercialPaper = selfIssueSomeCommercialPaper(cpOwnerKey.public, notary) + val commercialPaper = selfIssueSomeCommercialPaper(serviceHub.myInfo.legalIdentity, notary) progressTracker.currentStep = TRADING @@ -67,7 +68,7 @@ class SellerFlow(val otherParty: Party, } @Suspendable - fun selfIssueSomeCommercialPaper(ownedBy: PublicKey, notaryNode: NodeInfo): StateAndRef { + fun selfIssueSomeCommercialPaper(ownedBy: AbstractParty, notaryNode: NodeInfo): StateAndRef { // Make a fake company that's issued its own paper. val keyPair = generateKeyPair() val party = Party(BOC.name, keyPair.public) diff --git a/test-utils/src/main/kotlin/net/corda/testing/TransactionDSLInterpreter.kt b/test-utils/src/main/kotlin/net/corda/testing/TransactionDSLInterpreter.kt index 0dd8cda938..27d69dcc2e 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/TransactionDSLInterpreter.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/TransactionDSLInterpreter.kt @@ -79,7 +79,7 @@ class TransactionDSL(val interpreter: T) : Tr val transaction = ledgerInterpreter._unverifiedTransaction(null, TransactionBuilder(notary = DUMMY_NOTARY)) { output { state } // Add a dummy randomised output so that the transaction id differs when issuing the same state multiple times - val nonceState = DummyContract.SingleOwnerState(Random().nextInt(), DUMMY_NOTARY.owningKey) + val nonceState = DummyContract.SingleOwnerState(Random().nextInt(), DUMMY_NOTARY) output { nonceState } } input(transaction.outRef(0).ref) 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 7c42912740..8bc495dbc9 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 @@ -4,6 +4,7 @@ import net.corda.core.contracts.Attachment import net.corda.core.contracts.PartyAndReference import net.corda.core.crypto.* import net.corda.core.flows.StateMachineRunId +import net.corda.core.identity.AbstractParty import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import net.corda.core.messaging.SingleMessageRecipient @@ -28,7 +29,6 @@ import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.File import java.io.InputStream -import java.nio.file.Path import java.nio.file.Paths import java.security.KeyPair import java.security.PrivateKey @@ -90,7 +90,7 @@ class MockIdentityService(val identities: List, } override fun getAllIdentities(): Iterable = ArrayList(keyToParties.values) - override fun partyFromAnonymous(party: AnonymousParty): Party? = keyToParties[party.owningKey] + 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)] diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/views/GuiUtilities.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/views/GuiUtilities.kt index 876e217e7c..73e7aeefa2 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/views/GuiUtilities.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/views/GuiUtilities.kt @@ -15,7 +15,7 @@ import net.corda.client.jfx.model.NetworkIdentityModel import net.corda.client.jfx.utils.map import net.corda.contracts.asset.Cash import net.corda.core.contracts.StateAndRef -import net.corda.core.identity.AnonymousParty +import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import tornadofx.* @@ -91,4 +91,4 @@ fun Collection.cross(other: Collection) = this.flatMap { a -> other // TODO: This is a temporary fix for the UI to show the correct issuer identity, this will break when we start randomizing keys. More work is needed here when the identity work is done. fun StateAndRef.resolveIssuer(): ObservableValue = state.data.amount.token.issuer.party.resolveIssuer() -fun AnonymousParty.resolveIssuer(): ObservableValue = Models.get(NetworkIdentityModel::class, javaClass.kotlin).lookup(owningKey).map { it?.legalIdentity } +fun AbstractParty.resolveIssuer(): ObservableValue = Models.get(NetworkIdentityModel::class, javaClass.kotlin).lookup(owningKey).map { it?.legalIdentity } diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/views/Network.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/views/Network.kt index 9c705e79ff..a72f452a59 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/views/Network.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/views/Network.kt @@ -170,7 +170,7 @@ class Network : CordaView() { return Point2D(x, y) } - private fun List.getParties() = map { it.participants.map { getModel().lookup(it) } }.flatten() + private fun List.getParties() = map { it.participants.map { getModel().lookup(it.owningKey) } }.flatten() private fun fireBulletBetweenNodes(senderNode: Party, destNode: Party, startType: String, endType: String) { allComponentMap[senderNode]?.let { senderNode -> diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/views/TransactionViewer.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/views/TransactionViewer.kt index 4eb6acb584..71416b17e6 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/views/TransactionViewer.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/views/TransactionViewer.kt @@ -175,7 +175,7 @@ class TransactionViewer : CordaView("Transactions") { }.filterNotNull().toSet().joinToString(separator) } - private fun ObservableList>.getParties() = map { it.state.data.participants.map { getModel().lookup(it) } } + private fun ObservableList>.getParties() = map { it.state.data.participants.map { getModel().lookup(it.owningKey) } } private fun ObservableList>.toText() = map { it.contract().javaClass.simpleName }.groupBy { it }.map { "${it.key} (${it.value.size})" }.joinToString() private class TransactionWidget : BorderPane() { @@ -243,7 +243,7 @@ class TransactionViewer : CordaView("Transactions") { } row { label("Issuer :") { gridpaneConstraints { hAlignment = HPos.RIGHT } } - val anonymousIssuer: AnonymousParty = data.amount.token.issuer.party + val anonymousIssuer: AbstractParty = data.amount.token.issuer.party val issuer: AbstractParty = anonymousIssuer.resolveIssuer().value ?: anonymousIssuer // TODO: Anonymous should probably be italicised or similar label(issuer.nameOrNull()?.let { PartyNameFormatter.short.format(it) } ?: "Anonymous") { @@ -253,9 +253,9 @@ class TransactionViewer : CordaView("Transactions") { row { label("Owner :") { gridpaneConstraints { hAlignment = HPos.RIGHT } } val owner = data.owner - val nodeInfo = getModel().lookup(owner) + val nodeInfo = getModel().lookup(owner.owningKey) label(nodeInfo.map { it?.legalIdentity?.let { PartyNameFormatter.short.format(it.name) } ?: "???" }) { - tooltip(data.owner.toBase58String()) + tooltip(data.owner.owningKey.toBase58String()) } } } @@ -278,17 +278,17 @@ private fun calculateTotalEquiv(identity: NodeInfo?, inputs: List, outputs: List): AmountDiff { val (reportingCurrency, exchange) = reportingCurrencyExchange - val publicKey = identity?.legalIdentity?.owningKey + val legalIdentity = identity?.legalIdentity fun List.sum() = this.map { it as? Cash.State } .filterNotNull() - .filter { publicKey == it.owner } + .filter { legalIdentity == it.owner } .map { exchange(it.amount.withoutIssuer()).quantity } .sum() // For issuing cash, if I am the issuer and not the owner (e.g. issuing cash to other party), count it as negative. val issuedAmount = if (inputs.isEmpty()) outputs.map { it as? Cash.State } .filterNotNull() - .filter { publicKey == it.amount.token.issuer.party.owningKey && publicKey != it.owner } + .filter { legalIdentity == it.amount.token.issuer.party && legalIdentity != it.owner } .map { exchange(it.amount.withoutIssuer()).quantity } .sum() else 0 diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/views/cordapps/cash/CashViewer.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/views/cordapps/cash/CashViewer.kt index 48b9b2a696..0d4f8f16d7 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/views/cordapps/cash/CashViewer.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/views/cordapps/cash/CashViewer.kt @@ -23,8 +23,8 @@ 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.identity.AbstractParty import net.corda.core.crypto.commonName +import net.corda.core.identity.AbstractParty import net.corda.explorer.formatters.AmountFormatter import net.corda.explorer.formatters.PartyNameFormatter import net.corda.explorer.identicon.identicon diff --git a/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/CrossCashTest.kt b/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/CrossCashTest.kt index f188407b13..dba8704cd6 100644 --- a/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/CrossCashTest.kt +++ b/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/CrossCashTest.kt @@ -105,7 +105,7 @@ data class CrossCashState( it.value.map { val notifier = it.key " $notifier: [" + it.value.map { - Issued(PartyAndReference(it.first.toAnonymous(), OpaqueBytes.of(0)), it.second) + Issued(PartyAndReference(it.first, OpaqueBytes.of(0)), it.second) }.joinToString(",") + "]" }.joinToString("\n") }.joinToString("\n") diff --git a/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/NotaryTest.kt b/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/NotaryTest.kt index ffbb91656c..435809b20b 100644 --- a/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/NotaryTest.kt +++ b/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/NotaryTest.kt @@ -29,7 +29,7 @@ val dummyNotarisationTest = LoadTest( signWith(DUMMY_CASH_ISSUER_KEY) } val asset = issueTx.toWireTransaction().outRef(0) - val moveTx = DummyContract.move(asset, DUMMY_CASH_ISSUER.party.owningKey).apply { + val moveTx = DummyContract.move(asset, DUMMY_CASH_ISSUER.party).apply { signWith(DUMMY_CASH_ISSUER_KEY) } NotariseCommand(issueTx.toSignedTransaction(false), moveTx.toSignedTransaction(false), node) diff --git a/verifier/src/integration-test/kotlin/net/corda/verifier/GeneratedLedger.kt b/verifier/src/integration-test/kotlin/net/corda/verifier/GeneratedLedger.kt index 42aa9c5488..78a84a497d 100644 --- a/verifier/src/integration-test/kotlin/net/corda/verifier/GeneratedLedger.kt +++ b/verifier/src/integration-test/kotlin/net/corda/verifier/GeneratedLedger.kt @@ -3,6 +3,8 @@ package net.corda.verifier import net.corda.client.mock.* import net.corda.core.contracts.* import net.corda.core.crypto.* +import net.corda.core.identity.AbstractParty +import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.WireTransaction @@ -135,7 +137,7 @@ data class GeneratedLedger( val newNotaryGen = pickOneOrMaybeNew(identities - inputNotary, partyGenerator) val inputsGen = Generator.sampleBernoulli(inputsToChooseFrom) return inputsGen.bind { inputs -> - val signers = inputs.flatMap { it.state.data.participants } + inputNotary.owningKey + val signers: List = (inputs.flatMap { it.state.data.participants } + inputNotary).map { it.owningKey } val outputsGen = Generator.sequence(inputs.map { input -> newNotaryGen.map { TransactionState(input.state.data, it, null) } }) outputsGen.combine(attachmentsGenerator) { outputs, txAttachments -> val newNotaries = outputs.map { it.notary } @@ -185,7 +187,7 @@ data class GeneratedLedger( data class GeneratedState( val nonce: Long, - override val participants: List + override val participants: List ) : ContractState { override val contract = DummyContract() } @@ -205,7 +207,7 @@ val keyPairGenerator = Generator.long().map { entropyToKeyPair(BigInteger.valueO val publicKeyGenerator = keyPairGenerator.map { it.public } val stateGenerator: Generator = Generator.replicatePoisson(2.0, publicKeyGenerator).combine(Generator.long()) { participants, nonce -> - GeneratedState(nonce, participants) + GeneratedState(nonce, participants.map { AnonymousParty(it) }) } fun commandGenerator(partiesToPickFrom: Collection): Generator> {