mirror of
https://github.com/corda/corda.git
synced 2024-12-19 21:17:58 +00:00
CORDA-499: Dokka cleanup (#1575)
* Make functions in CompositeSignature static * Make contract IDs constant * Remove use of "e.g." which Dokka will take as end of the first sentence * Move example onto function that it actually works with * Change comment which refers to comment above it, without any linkage, to directly describe the function * Move implementation notes out of Dokka comment * Change contract IDs to constants in companion objects
This commit is contained in:
parent
4030903fee
commit
da82a0be40
@ -6,14 +6,13 @@ import com.nhaarman.mockito_kotlin.whenever
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.cordapp.CordappProvider
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.finance.USD
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.finance.USD
|
||||
import net.corda.testing.ALICE_PUBKEY
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.MINI_CORP
|
||||
import net.corda.testing.TestDependencyInjectionBase
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.i2p.crypto.eddsa.EdDSAPublicKey
|
||||
import org.junit.Before
|
||||
@ -72,7 +71,7 @@ class JacksonSupportTest : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun writeTransaction() {
|
||||
val attachmentRef = SecureHash.randomSHA256()
|
||||
whenever(cordappProvider.getContractAttachmentID(DUMMY_PROGRAM_ID))
|
||||
whenever(cordappProvider.getContractAttachmentID(DummyContract.PROGRAM_ID))
|
||||
.thenReturn(attachmentRef)
|
||||
fun makeDummyTx(): SignedTransaction {
|
||||
val wtx = DummyContract.generateInitial(1, DUMMY_NOTARY, MINI_CORP.ref(1))
|
||||
|
@ -10,7 +10,7 @@ import net.corda.core.transactions.ComponentVisibilityException
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.contracts.DummyState
|
||||
import org.junit.Test
|
||||
import java.time.Instant
|
||||
@ -19,7 +19,7 @@ import kotlin.test.*
|
||||
|
||||
class CompatibleTransactionTests : TestDependencyInjectionBase() {
|
||||
|
||||
private val dummyOutState = TransactionState(DummyState(0), DUMMY_PROGRAM_ID, DUMMY_NOTARY)
|
||||
private val dummyOutState = TransactionState(DummyState(0), DummyContract.PROGRAM_ID, DUMMY_NOTARY)
|
||||
private val stateRef1 = StateRef(SecureHash.randomSHA256(), 0)
|
||||
private val stateRef2 = StateRef(SecureHash.randomSHA256(), 1)
|
||||
private val stateRef3 = StateRef(SecureHash.randomSHA256(), 0)
|
||||
|
@ -1,20 +1,12 @@
|
||||
package net.corda.core.contracts
|
||||
|
||||
import com.nhaarman.mockito_kotlin.mock
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.contracts.DummyContractV2
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.node.ServicesForResolution
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DUMMY_V2_PROGRAM_ID
|
||||
import net.corda.testing.TestDependencyInjectionBase
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.contracts.DummyContractV2
|
||||
import net.corda.testing.node.MockServices
|
||||
import net.corda.testing.setCordappPackages
|
||||
import net.corda.testing.unsetCordappPackages
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
@ -27,14 +19,14 @@ class DummyContractV2Tests : TestDependencyInjectionBase() {
|
||||
fun `upgrade from v1`() {
|
||||
val services = MockServices()
|
||||
val contractUpgrade = DummyContractV2()
|
||||
val v1State = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DUMMY_PROGRAM_ID, DUMMY_NOTARY, constraint = AlwaysAcceptAttachmentConstraint)
|
||||
val v1State = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DummyContract.PROGRAM_ID, DUMMY_NOTARY, constraint = AlwaysAcceptAttachmentConstraint)
|
||||
val v1Ref = StateRef(SecureHash.randomSHA256(), 0)
|
||||
val v1StateAndRef = StateAndRef(v1State, v1Ref)
|
||||
val (tx, _) = DummyContractV2().generateUpgradeFromV1(services, v1StateAndRef)
|
||||
|
||||
assertEquals(v1Ref, tx.inputs.single())
|
||||
|
||||
val expectedOutput = TransactionState(contractUpgrade.upgrade(v1State.data), DUMMY_V2_PROGRAM_ID, DUMMY_NOTARY, constraint = AlwaysAcceptAttachmentConstraint)
|
||||
val expectedOutput = TransactionState(contractUpgrade.upgrade(v1State.data), DummyContractV2.PROGRAM_ID, DUMMY_NOTARY, constraint = AlwaysAcceptAttachmentConstraint)
|
||||
val actualOutput = tx.outputs.single()
|
||||
assertEquals(expectedOutput, actualOutput)
|
||||
|
||||
|
@ -6,7 +6,7 @@ import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.TestDependencyInjectionBase
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.Before
|
||||
@ -22,7 +22,7 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
services.mockCordappProvider.addMockCordapp(DUMMY_PROGRAM_ID, services)
|
||||
services.mockCordappProvider.addMockCordapp(DummyContract.PROGRAM_ID, services)
|
||||
}
|
||||
|
||||
interface Commands {
|
||||
@ -52,12 +52,12 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
val dummyState = makeDummyState(data)
|
||||
val fakeIssueTx = services.signInitialTransaction(
|
||||
TransactionBuilder(notary = DUMMY_NOTARY)
|
||||
.addOutputState(dummyState, DUMMY_PROGRAM_ID)
|
||||
.addOutputState(dummyState, DummyContract.PROGRAM_ID)
|
||||
.addCommand(dummyCommand())
|
||||
)
|
||||
services.recordTransactions(fakeIssueTx)
|
||||
val dummyStateRef = StateRef(fakeIssueTx.id, 0)
|
||||
return StateAndRef(TransactionState(dummyState, DUMMY_PROGRAM_ID, DUMMY_NOTARY, null), dummyStateRef)
|
||||
return StateAndRef(TransactionState(dummyState, DummyContract.PROGRAM_ID, DUMMY_NOTARY, null), dummyStateRef)
|
||||
}
|
||||
|
||||
private fun makeDummyTransaction(): LedgerTransaction {
|
||||
@ -65,8 +65,8 @@ class LedgerTransactionQueryTests : TestDependencyInjectionBase() {
|
||||
for (i in 0..4) {
|
||||
tx.addInputState(makeDummyStateAndRef(i))
|
||||
tx.addInputState(makeDummyStateAndRef(i.toString()))
|
||||
tx.addOutputState(makeDummyState(i), DUMMY_PROGRAM_ID)
|
||||
tx.addOutputState(makeDummyState(i.toString()), DUMMY_PROGRAM_ID)
|
||||
tx.addOutputState(makeDummyState(i), DummyContract.PROGRAM_ID)
|
||||
tx.addOutputState(makeDummyState(i.toString()), DummyContract.PROGRAM_ID)
|
||||
tx.addCommand(Commands.Cmd1(i), listOf(services.myInfo.chooseIdentity().owningKey))
|
||||
tx.addCommand(Commands.Cmd2(i), listOf(services.myInfo.chooseIdentity().owningKey))
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
import net.corda.finance.DOLLARS
|
||||
import net.corda.finance.`issued by`
|
||||
import net.corda.finance.contracts.asset.CASH_PROGRAM_ID
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.testing.MEGA_CORP
|
||||
import net.corda.testing.MINI_CORP
|
||||
@ -48,9 +47,9 @@ class TransactionEncumbranceTests {
|
||||
fun `state can be encumbered`() {
|
||||
ledger {
|
||||
transaction {
|
||||
attachments(CASH_PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
input(CASH_PROGRAM_ID) { state }
|
||||
output(CASH_PROGRAM_ID, encumbrance = 1) { stateWithNewOwner }
|
||||
attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
input(Cash.PROGRAM_ID) { state }
|
||||
output(Cash.PROGRAM_ID, encumbrance = 1) { stateWithNewOwner }
|
||||
output(TEST_TIMELOCK_ID, "5pm time-lock") { timeLock }
|
||||
command(MEGA_CORP.owningKey) { Cash.Commands.Move() }
|
||||
verifies()
|
||||
@ -62,16 +61,16 @@ class TransactionEncumbranceTests {
|
||||
fun `state can transition if encumbrance rules are met`() {
|
||||
ledger {
|
||||
unverifiedTransaction {
|
||||
attachments(CASH_PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
output(CASH_PROGRAM_ID, "state encumbered by 5pm time-lock") { state }
|
||||
attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
output(Cash.PROGRAM_ID, "state encumbered by 5pm time-lock") { state }
|
||||
output(TEST_TIMELOCK_ID, "5pm time-lock") { timeLock }
|
||||
}
|
||||
// Un-encumber the output if the time of the transaction is later than the timelock.
|
||||
transaction {
|
||||
attachments(CASH_PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
input("state encumbered by 5pm time-lock")
|
||||
input("5pm time-lock")
|
||||
output(CASH_PROGRAM_ID) { stateWithNewOwner }
|
||||
output(Cash.PROGRAM_ID) { stateWithNewOwner }
|
||||
command(MEGA_CORP.owningKey) { Cash.Commands.Move() }
|
||||
timeWindow(FIVE_PM)
|
||||
verifies()
|
||||
@ -83,16 +82,16 @@ class TransactionEncumbranceTests {
|
||||
fun `state cannot transition if the encumbrance contract fails to verify`() {
|
||||
ledger {
|
||||
unverifiedTransaction {
|
||||
attachments(CASH_PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
output(CASH_PROGRAM_ID, "state encumbered by 5pm time-lock") { state }
|
||||
attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
output(Cash.PROGRAM_ID, "state encumbered by 5pm time-lock") { state }
|
||||
output(TEST_TIMELOCK_ID, "5pm time-lock") { timeLock }
|
||||
}
|
||||
// The time of the transaction is earlier than the time specified in the encumbering timelock.
|
||||
transaction {
|
||||
attachments(CASH_PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
input("state encumbered by 5pm time-lock")
|
||||
input("5pm time-lock")
|
||||
output(CASH_PROGRAM_ID) { state }
|
||||
output(Cash.PROGRAM_ID) { state }
|
||||
command(MEGA_CORP.owningKey) { Cash.Commands.Move() }
|
||||
timeWindow(FOUR_PM)
|
||||
this `fails with` "the time specified in the time-lock has passed"
|
||||
@ -104,14 +103,14 @@ class TransactionEncumbranceTests {
|
||||
fun `state must be consumed along with its encumbrance`() {
|
||||
ledger {
|
||||
unverifiedTransaction {
|
||||
attachments(CASH_PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
output(CASH_PROGRAM_ID, "state encumbered by 5pm time-lock", encumbrance = 1) { state }
|
||||
attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
output(Cash.PROGRAM_ID, "state encumbered by 5pm time-lock", encumbrance = 1) { state }
|
||||
output(TEST_TIMELOCK_ID, "5pm time-lock") { timeLock }
|
||||
}
|
||||
transaction {
|
||||
attachments(CASH_PROGRAM_ID)
|
||||
attachments(Cash.PROGRAM_ID)
|
||||
input("state encumbered by 5pm time-lock")
|
||||
output(CASH_PROGRAM_ID) { stateWithNewOwner }
|
||||
output(Cash.PROGRAM_ID) { stateWithNewOwner }
|
||||
command(MEGA_CORP.owningKey) { Cash.Commands.Move() }
|
||||
timeWindow(FIVE_PM)
|
||||
this `fails with` "Missing required encumbrance 1 in INPUT"
|
||||
@ -123,9 +122,9 @@ class TransactionEncumbranceTests {
|
||||
fun `state cannot be encumbered by itself`() {
|
||||
ledger {
|
||||
transaction {
|
||||
attachments(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { state }
|
||||
output(CASH_PROGRAM_ID, encumbrance = 0) { stateWithNewOwner }
|
||||
attachments(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { state }
|
||||
output(Cash.PROGRAM_ID, encumbrance = 0) { stateWithNewOwner }
|
||||
command(MEGA_CORP.owningKey) { Cash.Commands.Move() }
|
||||
this `fails with` "Missing required encumbrance 0 in OUTPUT"
|
||||
}
|
||||
@ -136,8 +135,8 @@ class TransactionEncumbranceTests {
|
||||
fun `encumbrance state index must be valid`() {
|
||||
ledger {
|
||||
transaction {
|
||||
attachments(CASH_PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
input(CASH_PROGRAM_ID) { state }
|
||||
attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
input(Cash.PROGRAM_ID) { state }
|
||||
output(TEST_TIMELOCK_ID, encumbrance = 2) { stateWithNewOwner }
|
||||
output(TEST_TIMELOCK_ID) { timeLock }
|
||||
command(MEGA_CORP.owningKey) { Cash.Commands.Move() }
|
||||
@ -150,16 +149,16 @@ class TransactionEncumbranceTests {
|
||||
fun `correct encumbrance state must be provided`() {
|
||||
ledger {
|
||||
unverifiedTransaction {
|
||||
attachments(CASH_PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
output(CASH_PROGRAM_ID, "state encumbered by some other state", encumbrance = 1) { state }
|
||||
output(CASH_PROGRAM_ID, "some other state") { state }
|
||||
attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
output(Cash.PROGRAM_ID, "state encumbered by some other state", encumbrance = 1) { state }
|
||||
output(Cash.PROGRAM_ID, "some other state") { state }
|
||||
output(TEST_TIMELOCK_ID, "5pm time-lock") { timeLock }
|
||||
}
|
||||
transaction {
|
||||
attachments(CASH_PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
attachments(Cash.PROGRAM_ID, TEST_TIMELOCK_ID)
|
||||
input("state encumbered by some other state")
|
||||
input("5pm time-lock")
|
||||
output(CASH_PROGRAM_ID) { stateWithNewOwner }
|
||||
output(Cash.PROGRAM_ID) { stateWithNewOwner }
|
||||
command(MEGA_CORP.owningKey) { Cash.Commands.Move() }
|
||||
timeWindow(FIVE_PM)
|
||||
this `fails with` "Missing required encumbrance 1 in INPUT"
|
||||
|
@ -8,7 +8,6 @@ import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER_KEY
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.node.MockAttachment
|
||||
import net.corda.testing.node.MockAttachmentStorage
|
||||
@ -96,11 +95,11 @@ class TransactionTests : TestDependencyInjectionBase() {
|
||||
|
||||
@Test
|
||||
fun `transactions with no inputs can have any notary`() {
|
||||
val baseOutState = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DUMMY_PROGRAM_ID, DUMMY_NOTARY, constraint = AlwaysAcceptAttachmentConstraint)
|
||||
val baseOutState = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DummyContract.PROGRAM_ID, DUMMY_NOTARY, constraint = AlwaysAcceptAttachmentConstraint)
|
||||
val inputs = emptyList<StateAndRef<*>>()
|
||||
val outputs = listOf(baseOutState, baseOutState.copy(notary = ALICE), baseOutState.copy(notary = BOB))
|
||||
val commands = emptyList<CommandWithParties<CommandData>>()
|
||||
val attachments = listOf<Attachment>(ContractAttachment(MockAttachment(), DUMMY_PROGRAM_ID))
|
||||
val attachments = listOf<Attachment>(ContractAttachment(MockAttachment(), DummyContract.PROGRAM_ID))
|
||||
val id = SecureHash.randomSHA256()
|
||||
val timeWindow: TimeWindow? = null
|
||||
val privacySalt: PrivacySalt = PrivacySalt()
|
||||
@ -136,7 +135,7 @@ class TransactionTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun `general transactions cannot change notary`() {
|
||||
val notary: Party = DUMMY_NOTARY
|
||||
val inState = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DUMMY_PROGRAM_ID, notary)
|
||||
val inState = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DummyContract.PROGRAM_ID, notary)
|
||||
val outState = inState.copy(notary = ALICE)
|
||||
val inputs = listOf(StateAndRef(inState, StateRef(SecureHash.randomSHA256(), 0)))
|
||||
val outputs = listOf(outState)
|
||||
@ -161,7 +160,7 @@ class TransactionTests : TestDependencyInjectionBase() {
|
||||
|
||||
@Test
|
||||
fun `transactions with identical contents must have different ids`() {
|
||||
val outputState = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DUMMY_PROGRAM_ID, DUMMY_NOTARY)
|
||||
val outputState = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DummyContract.PROGRAM_ID, DUMMY_NOTARY)
|
||||
fun buildTransaction() = WireTransaction(
|
||||
inputs = emptyList(),
|
||||
attachments = emptyList(),
|
||||
|
@ -9,7 +9,6 @@ import net.corda.core.serialization.serialize
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
import net.corda.finance.DOLLARS
|
||||
import net.corda.finance.`issued by`
|
||||
import net.corda.finance.contracts.asset.CASH_PROGRAM_ID
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.testing.*
|
||||
import org.junit.Test
|
||||
@ -32,14 +31,14 @@ class PartialMerkleTreeTest : TestDependencyInjectionBase() {
|
||||
|
||||
private val testLedger = ledger {
|
||||
unverifiedTransaction {
|
||||
attachments(CASH_PROGRAM_ID)
|
||||
output(CASH_PROGRAM_ID, "MEGA_CORP cash") {
|
||||
attachments(Cash.PROGRAM_ID)
|
||||
output(Cash.PROGRAM_ID, "MEGA_CORP cash") {
|
||||
Cash.State(
|
||||
amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
|
||||
owner = MEGA_CORP
|
||||
)
|
||||
}
|
||||
output(CASH_PROGRAM_ID, "dummy cash 1") {
|
||||
output(Cash.PROGRAM_ID, "dummy cash 1") {
|
||||
Cash.State(
|
||||
amount = 900.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
|
||||
owner = MINI_CORP
|
||||
@ -48,9 +47,9 @@ class PartialMerkleTreeTest : TestDependencyInjectionBase() {
|
||||
}
|
||||
|
||||
transaction {
|
||||
attachments(CASH_PROGRAM_ID)
|
||||
attachments(Cash.PROGRAM_ID)
|
||||
input("MEGA_CORP cash")
|
||||
output(CASH_PROGRAM_ID, "MEGA_CORP cash".output<Cash.State>().copy(owner = MINI_CORP))
|
||||
output(Cash.PROGRAM_ID, "MEGA_CORP cash".output<Cash.State>().copy(owner = MINI_CORP))
|
||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||
timeWindow(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
|
@ -13,9 +13,7 @@ import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.After
|
||||
@ -94,7 +92,7 @@ class CollectSignaturesFlowTests {
|
||||
|
||||
val myInputKeys = state.participants.map { it.owningKey }
|
||||
val command = Command(DummyContract.Commands.Create(), myInputKeys)
|
||||
val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), command)
|
||||
val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DummyContract.PROGRAM_ID), command)
|
||||
val ptx = serviceHub.signInitialTransaction(builder)
|
||||
val signature = subFlow(CollectSignatureFlow(ptx, initiatingSession, initiatingSession.counterparty.owningKey))
|
||||
val stx = ptx + signature
|
||||
@ -114,7 +112,7 @@ class CollectSignaturesFlowTests {
|
||||
val notary = serviceHub.getDefaultNotary()
|
||||
val myInputKeys = state.participants.map { it.owningKey }
|
||||
val command = Command(DummyContract.Commands.Create(), myInputKeys)
|
||||
val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), command)
|
||||
val builder = TransactionBuilder(notary).withItems(StateAndContract(state, DummyContract.PROGRAM_ID), command)
|
||||
val ptx = serviceHub.signInitialTransaction(builder)
|
||||
val sessions = excludeHostNode(serviceHub, groupAbstractPartyByWellKnownParty(serviceHub, state.owners)).map { initiateFlow(it.key) }
|
||||
val stx = subFlow(CollectSignaturesFlow(ptx, sessions, myInputKeys))
|
||||
|
@ -14,7 +14,6 @@ import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.finance.USD
|
||||
import net.corda.finance.`issued by`
|
||||
import net.corda.finance.contracts.asset.CASH_PROGRAM_ID
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.flows.CashIssueFlow
|
||||
import net.corda.node.internal.CordaRPCOpsImpl
|
||||
@ -234,7 +233,7 @@ class ContractUpgradeFlowTest {
|
||||
}
|
||||
|
||||
class CashV2 : UpgradedContract<Cash.State, CashV2.State> {
|
||||
override val legacyContract = CASH_PROGRAM_ID
|
||||
override val legacyContract = Cash.PROGRAM_ID
|
||||
|
||||
data class State(override val amount: Amount<Issued<Currency>>, val owners: List<AbstractParty>) : FungibleAsset<Currency> {
|
||||
override val owner: AbstractParty = owners.first()
|
||||
|
@ -20,7 +20,6 @@ import net.corda.core.utilities.ProgressTracker.Step;
|
||||
import net.corda.core.utilities.UntrustworthyData;
|
||||
import net.corda.finance.contracts.asset.Cash;
|
||||
import net.corda.testing.contracts.DummyContract;
|
||||
import net.corda.testing.contracts.DummyContractKt;
|
||||
import net.corda.testing.contracts.DummyState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -34,7 +33,6 @@ import java.util.Set;
|
||||
|
||||
import static net.corda.core.contracts.ContractsDSL.requireThat;
|
||||
import static net.corda.testing.TestConstants.getALICE_KEY;
|
||||
import static net.corda.testing.contracts.DummyContractKt.DUMMY_PROGRAM_ID;
|
||||
|
||||
// We group our two flows inside a singleton object to indicate that they work
|
||||
// together.
|
||||
@ -353,17 +351,17 @@ public class FlowCookbookJava {
|
||||
|
||||
// An output state can be added as a ``ContractState``, contract class name and notary.
|
||||
// DOCSTART 49
|
||||
txBuilder.addOutputState(ourOutputState, DUMMY_PROGRAM_ID, specificNotary);
|
||||
txBuilder.addOutputState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary);
|
||||
// DOCEND 49
|
||||
// We can also leave the notary field blank, in which case the transaction's default
|
||||
// notary is used.
|
||||
// DOCSTART 50
|
||||
txBuilder.addOutputState(ourOutputState, DUMMY_PROGRAM_ID);
|
||||
txBuilder.addOutputState(ourOutputState, DummyContract.PROGRAM_ID);
|
||||
// DOCEND 50
|
||||
// Or we can add the output state as a ``TransactionState``, which already specifies
|
||||
// the output's contract and notary.
|
||||
// DOCSTART 51
|
||||
TransactionState txState = new TransactionState(ourOutputState, DUMMY_PROGRAM_ID, specificNotary);
|
||||
TransactionState txState = new TransactionState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary);
|
||||
// DOCEND 51
|
||||
|
||||
// Commands can be added as ``Command``s.
|
||||
|
@ -23,7 +23,6 @@ import net.corda.core.utilities.seconds
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.testing.ALICE_PUBKEY
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.contracts.DummyState
|
||||
import java.security.PublicKey
|
||||
@ -333,17 +332,17 @@ object FlowCookbook {
|
||||
|
||||
// An output state can be added as a ``ContractState``, contract class name and notary.
|
||||
// DOCSTART 49
|
||||
txBuilder.addOutputState(ourOutputState, DUMMY_PROGRAM_ID, specificNotary)
|
||||
txBuilder.addOutputState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary)
|
||||
// DOCEND 49
|
||||
// We can also leave the notary field blank, in which case the transaction's default
|
||||
// notary is used.
|
||||
// DOCSTART 50
|
||||
txBuilder.addOutputState(ourOutputState, DUMMY_PROGRAM_ID)
|
||||
txBuilder.addOutputState(ourOutputState, DummyContract.PROGRAM_ID)
|
||||
// DOCEND 50
|
||||
// Or we can add the output state as a ``TransactionState``, which already specifies
|
||||
// the output's contract and notary.
|
||||
// DOCSTART 51
|
||||
val txState: TransactionState<DummyState> = TransactionState(ourOutputState, DUMMY_PROGRAM_ID, specificNotary)
|
||||
val txState: TransactionState<DummyState> = TransactionState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary)
|
||||
// DOCEND 51
|
||||
|
||||
// Commands can be added as ``Command``s.
|
||||
|
@ -14,7 +14,6 @@ import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.finance.contracts.asset.CASH_PROGRAM_ID
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.schemas.CashSchemaV1
|
||||
import net.corda.testing.chooseIdentity
|
||||
@ -184,8 +183,8 @@ class ForeignExchangeFlow(private val tradeId: String,
|
||||
// Build and add the inputs and outputs
|
||||
builder.withItems(*ourInputStates.toTypedArray())
|
||||
builder.withItems(*theirInputStates.toTypedArray())
|
||||
builder.withItems(*ourOutputState.map { StateAndContract(it, CASH_PROGRAM_ID) }.toTypedArray())
|
||||
builder.withItems(*theirOutputState.map { StateAndContract(it, CASH_PROGRAM_ID) }.toTypedArray())
|
||||
builder.withItems(*ourOutputState.map { StateAndContract(it, Cash.PROGRAM_ID) }.toTypedArray())
|
||||
builder.withItems(*theirOutputState.map { StateAndContract(it, Cash.PROGRAM_ID) }.toTypedArray())
|
||||
|
||||
// We have already validated their response and trust our own data
|
||||
// so we can sign. Note the returned SignedTransaction is still not fully signed
|
||||
|
@ -37,8 +37,6 @@ import java.util.concurrent.atomic.AtomicReference
|
||||
// Cash
|
||||
//
|
||||
|
||||
const val CASH_PROGRAM_ID: ContractClassName = "net.corda.finance.contracts.asset.Cash"
|
||||
|
||||
/**
|
||||
* Pluggable interface to allow for different cash selection provider implementations
|
||||
* Default implementation [CashSelectionH2Impl] uses H2 database and a custom function within H2 to perform aggregation.
|
||||
@ -190,7 +188,7 @@ class Cash : OnLedgerAsset<Currency, Cash.Commands, Cash.State>() {
|
||||
* Puts together an issuance transaction for the specified amount that starts out being owned by the given pubkey.
|
||||
*/
|
||||
fun generateIssue(tx: TransactionBuilder, amount: Amount<Issued<Currency>>, owner: AbstractParty, notary: Party)
|
||||
= generateIssue(tx, TransactionState(State(amount, owner), CASH_PROGRAM_ID, notary), Commands.Issue())
|
||||
= generateIssue(tx, TransactionState(State(amount, owner), PROGRAM_ID, notary), Commands.Issue())
|
||||
|
||||
override fun deriveState(txState: TransactionState<State>, amount: Amount<Issued<Currency>>, owner: AbstractParty)
|
||||
= txState.copy(data = txState.data.copy(amount = amount, owner = owner))
|
||||
@ -266,6 +264,8 @@ class Cash : OnLedgerAsset<Currency, Cash.Commands, Cash.State>() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PROGRAM_ID: ContractClassName = "net.corda.finance.contracts.asset.Cash"
|
||||
|
||||
/**
|
||||
* Generate a transaction that moves an amount of currency to the given party, and sends any change back to
|
||||
* sole identity of the calling node. Fails for nodes with multiple identities.
|
||||
|
@ -32,8 +32,7 @@ import java.util.*
|
||||
// TODO: Need to think about expiry of commodities, how to require payment of storage costs, etc.
|
||||
class CommodityContract : OnLedgerAsset<Commodity, CommodityContract.Commands, CommodityContract.State>() {
|
||||
companion object {
|
||||
// Just a fake program identifier for now. In a real system it could be, for instance, the hash of the program bytecode.
|
||||
val COMMODITY_PROGRAM_ID = "net.corda.finance.contracts.asset.CommodityContract"
|
||||
const val PROGRAM_ID: ContractClassName = "net.corda.finance.contracts.asset.CommodityContract"
|
||||
}
|
||||
|
||||
/** A state representing a commodity claim against some party */
|
||||
@ -158,7 +157,7 @@ class CommodityContract : OnLedgerAsset<Commodity, CommodityContract.Commands, C
|
||||
* Puts together an issuance transaction for the specified amount that starts out being owned by the given pubkey.
|
||||
*/
|
||||
fun generateIssue(tx: TransactionBuilder, amount: Amount<Issued<Commodity>>, owner: AbstractParty, notary: Party)
|
||||
= generateIssue(tx, TransactionState(State(amount, owner), COMMODITY_PROGRAM_ID, notary), Commands.Issue())
|
||||
= generateIssue(tx, TransactionState(State(amount, owner), PROGRAM_ID, notary), Commands.Issue())
|
||||
|
||||
|
||||
override fun deriveState(txState: TransactionState<State>, amount: Amount<Issued<Commodity>>, owner: AbstractParty)
|
||||
|
@ -61,9 +61,6 @@ data class MultilateralNetState<P : Any>(
|
||||
override val template: Obligation.Terms<P>
|
||||
) : NetState<P>
|
||||
|
||||
|
||||
const val OBLIGATION_PROGRAM_ID: ContractClassName = "net.corda.finance.contracts.asset.Obligation"
|
||||
|
||||
/**
|
||||
* An obligation contract commits the obligor to delivering a specified amount of a fungible asset (for example the
|
||||
* [Cash] contract) at a specified future point in time. Settlement transactions may split and merge contracts across
|
||||
@ -73,6 +70,9 @@ const val OBLIGATION_PROGRAM_ID: ContractClassName = "net.corda.finance.contract
|
||||
* @param P the product the obligation is for payment of.
|
||||
*/
|
||||
class Obligation<P : Any> : Contract {
|
||||
companion object {
|
||||
const val PROGRAM_ID: ContractClassName = "net.corda.finance.contracts.asset.Obligation"
|
||||
}
|
||||
/**
|
||||
* Represents where in its lifecycle a contract state is, which in turn controls the commands that can be applied
|
||||
* to the state. Most states will not leave the [NORMAL] lifecycle. Note that settled (as an end lifecycle) is
|
||||
@ -488,7 +488,7 @@ class Obligation<P : Any> : Contract {
|
||||
tx.withItems(*inputs)
|
||||
val out = states.reduce(State<P>::net)
|
||||
if (out.quantity > 0L)
|
||||
tx.addOutputState(out, OBLIGATION_PROGRAM_ID)
|
||||
tx.addOutputState(out, PROGRAM_ID)
|
||||
tx.addCommand(Commands.Net(NetType.PAYMENT), signer.owningKey)
|
||||
}
|
||||
|
||||
@ -531,7 +531,7 @@ class Obligation<P : Any> : Contract {
|
||||
beneficiary: AbstractParty,
|
||||
notary: Party) {
|
||||
val issuanceDef = Terms(NonEmptySet.of(acceptableContract), NonEmptySet.of(amount.token), dueBefore)
|
||||
OnLedgerAsset.generateIssue(tx, TransactionState(State(Lifecycle.NORMAL, obligor, issuanceDef, amount.quantity, beneficiary), OBLIGATION_PROGRAM_ID, notary), Commands.Issue())
|
||||
OnLedgerAsset.generateIssue(tx, TransactionState(State(Lifecycle.NORMAL, obligor, issuanceDef, amount.quantity, beneficiary), PROGRAM_ID, notary), Commands.Issue())
|
||||
}
|
||||
|
||||
/**
|
||||
@ -551,7 +551,7 @@ class Obligation<P : Any> : Contract {
|
||||
pennies: Long,
|
||||
beneficiary: AbstractParty,
|
||||
notary: Party)
|
||||
= OnLedgerAsset.generateIssue(tx, TransactionState(State(Lifecycle.NORMAL, obligor, issuanceDef, pennies, beneficiary), OBLIGATION_PROGRAM_ID, notary), Commands.Issue())
|
||||
= OnLedgerAsset.generateIssue(tx, TransactionState(State(Lifecycle.NORMAL, obligor, issuanceDef, pennies, beneficiary), PROGRAM_ID, notary), Commands.Issue())
|
||||
|
||||
fun generatePaymentNetting(tx: TransactionBuilder,
|
||||
issued: Issued<Obligation.Terms<P>>,
|
||||
@ -584,7 +584,7 @@ class Obligation<P : Any> : Contract {
|
||||
netState.template, entry.value.quantity, entry.key.second)
|
||||
}
|
||||
// Add the new states to the TX
|
||||
.forEach { tx.addOutputState(it, OBLIGATION_PROGRAM_ID, notary) }
|
||||
.forEach { tx.addOutputState(it, PROGRAM_ID, notary) }
|
||||
tx.addCommand(Commands.Net(NetType.PAYMENT), signers.map { it.owningKey })
|
||||
}
|
||||
|
||||
@ -615,7 +615,7 @@ class Obligation<P : Any> : Contract {
|
||||
stateAndRefs.forEach { stateAndRef ->
|
||||
val outState = stateAndRef.state.data.copy(lifecycle = lifecycle)
|
||||
tx.addInputState(stateAndRef)
|
||||
tx.addOutputState(outState, OBLIGATION_PROGRAM_ID, notary)
|
||||
tx.addOutputState(outState, PROGRAM_ID, notary)
|
||||
partiesUsed.add(stateAndRef.state.data.beneficiary)
|
||||
}
|
||||
tx.addCommand(Commands.SetLifecycle(lifecycle), partiesUsed.map { it.owningKey }.distinct())
|
||||
@ -668,13 +668,13 @@ class Obligation<P : Any> : Contract {
|
||||
val assetState = ref.state.data
|
||||
val amount = Amount(assetState.amount.quantity, assetState.amount.token.product)
|
||||
if (obligationRemaining >= amount) {
|
||||
tx.addOutputState(assetState.withNewOwnerAndAmount(assetState.amount, obligationOwner), OBLIGATION_PROGRAM_ID, notary)
|
||||
tx.addOutputState(assetState.withNewOwnerAndAmount(assetState.amount, obligationOwner), PROGRAM_ID, notary)
|
||||
obligationRemaining -= amount
|
||||
} else {
|
||||
val change = Amount(obligationRemaining.quantity, assetState.amount.token)
|
||||
// Split the state in two, sending the change back to the previous beneficiary
|
||||
tx.addOutputState(assetState.withNewOwnerAndAmount(change, obligationOwner), OBLIGATION_PROGRAM_ID, notary)
|
||||
tx.addOutputState(assetState.withNewOwnerAndAmount(assetState.amount - change, assetState.owner), OBLIGATION_PROGRAM_ID, notary)
|
||||
tx.addOutputState(assetState.withNewOwnerAndAmount(change, obligationOwner), PROGRAM_ID, notary)
|
||||
tx.addOutputState(assetState.withNewOwnerAndAmount(assetState.amount - change, assetState.owner), PROGRAM_ID, notary)
|
||||
obligationRemaining -= Amount(0L, obligationRemaining.token)
|
||||
}
|
||||
assetSigners.add(assetState.owner)
|
||||
@ -683,7 +683,7 @@ class Obligation<P : Any> : Contract {
|
||||
|
||||
// If we haven't cleared the full obligation, add the remainder as an output
|
||||
if (obligationRemaining.quantity > 0L) {
|
||||
tx.addOutputState(State(Lifecycle.NORMAL, obligationIssuer, template, obligationRemaining.quantity, obligationOwner), OBLIGATION_PROGRAM_ID, notary)
|
||||
tx.addOutputState(State(Lifecycle.NORMAL, obligationIssuer, template, obligationRemaining.quantity, obligationOwner), PROGRAM_ID, notary)
|
||||
} else {
|
||||
// Destroy all of the states
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import org.junit.Test;
|
||||
import static net.corda.finance.Currencies.DOLLARS;
|
||||
import static net.corda.finance.Currencies.issuedBy;
|
||||
import static net.corda.testing.CoreTestUtils.*;
|
||||
import static net.corda.testing.NodeTestUtils.*;
|
||||
import static net.corda.testing.NodeTestUtils.transaction;
|
||||
|
||||
/**
|
||||
* This is an incomplete Java replica of CashTests.kt to show how to use the Java test DSL
|
||||
@ -19,44 +19,43 @@ public class CashTestsJava {
|
||||
private final PartyAndReference defaultIssuer = getMEGA_CORP().ref(defaultRef);
|
||||
private final Cash.State inState = new Cash.State(issuedBy(DOLLARS(1000), defaultIssuer), new AnonymousParty(getMEGA_CORP_PUBKEY()));
|
||||
private final Cash.State outState = new Cash.State(inState.getAmount(), new AnonymousParty(getMINI_CORP_PUBKEY()));
|
||||
private final String CASH_PROGRAM_ID = CashUtilities.CASH_PROGRAM_ID;
|
||||
|
||||
@Test
|
||||
public void trivial() {
|
||||
transaction(tx -> {
|
||||
tx.attachment(CASH_PROGRAM_ID);
|
||||
tx.attachment(Cash.PROGRAM_ID);
|
||||
|
||||
tx.input(CASH_PROGRAM_ID, inState);
|
||||
tx.input(Cash.PROGRAM_ID, inState);
|
||||
|
||||
tx.tweak(tw -> {
|
||||
tw.output(CASH_PROGRAM_ID, () -> new Cash.State(issuedBy(DOLLARS(2000), defaultIssuer), new AnonymousParty(getMINI_CORP_PUBKEY())));
|
||||
tw.output(Cash.PROGRAM_ID, () -> new Cash.State(issuedBy(DOLLARS(2000), defaultIssuer), new AnonymousParty(getMINI_CORP_PUBKEY())));
|
||||
tw.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move());
|
||||
return tw.failsWith("the amounts balance");
|
||||
});
|
||||
|
||||
tx.tweak(tw -> {
|
||||
tw.output(CASH_PROGRAM_ID, () -> outState );
|
||||
tw.output(Cash.PROGRAM_ID, () -> outState );
|
||||
tw.command(getMEGA_CORP_PUBKEY(), DummyCommandData.INSTANCE);
|
||||
// Invalid command
|
||||
return tw.failsWith("required net.corda.finance.contracts.asset.Cash.Commands.Move command");
|
||||
});
|
||||
tx.tweak(tw -> {
|
||||
tw.output(CASH_PROGRAM_ID, () -> outState);
|
||||
tw.output(Cash.PROGRAM_ID, () -> outState);
|
||||
tw.command(getMINI_CORP_PUBKEY(), new Cash.Commands.Move());
|
||||
return tw.failsWith("the owning keys are a subset of the signing keys");
|
||||
});
|
||||
tx.tweak(tw -> {
|
||||
tw.output(CASH_PROGRAM_ID, () -> outState);
|
||||
tw.output(Cash.PROGRAM_ID, () -> outState);
|
||||
// issuedBy() can't be directly imported because it conflicts with other identically named functions
|
||||
// with different overloads (for some reason).
|
||||
tw.output(CASH_PROGRAM_ID, () -> outState.issuedBy(getMINI_CORP()));
|
||||
tw.output(Cash.PROGRAM_ID, () -> outState.issuedBy(getMINI_CORP()));
|
||||
tw.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move());
|
||||
return tw.failsWith("at least one cash input");
|
||||
});
|
||||
|
||||
// Simple reallocation works.
|
||||
return tx.tweak(tw -> {
|
||||
tw.output(CASH_PROGRAM_ID, () -> outState);
|
||||
tw.output(Cash.PROGRAM_ID, () -> outState);
|
||||
tw.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move());
|
||||
return tw.verifies();
|
||||
});
|
||||
|
@ -94,9 +94,9 @@ class CommercialPaperTestsGeneric {
|
||||
val someProfits = 1200.DOLLARS `issued by` issuer
|
||||
ledger {
|
||||
unverifiedTransaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
output(CASH_PROGRAM_ID, "alice's $900", 900.DOLLARS.CASH `issued by` issuer `owned by` ALICE)
|
||||
output(CASH_PROGRAM_ID, "some profits", someProfits.STATE `owned by` MEGA_CORP)
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
output(Cash.PROGRAM_ID, "alice's $900", 900.DOLLARS.CASH `issued by` issuer `owned by` ALICE)
|
||||
output(Cash.PROGRAM_ID, "some profits", someProfits.STATE `owned by` MEGA_CORP)
|
||||
}
|
||||
|
||||
// Some CP is issued onto the ledger by MegaCorp.
|
||||
@ -111,10 +111,10 @@ class CommercialPaperTestsGeneric {
|
||||
// The CP is sold to alice for her $900, $100 less than the face value. At 10% interest after only 7 days,
|
||||
// that sounds a bit too good to be true!
|
||||
transaction("Trade") {
|
||||
attachments(CASH_PROGRAM_ID, JavaCommercialPaper.JCP_PROGRAM_ID)
|
||||
attachments(Cash.PROGRAM_ID, JavaCommercialPaper.JCP_PROGRAM_ID)
|
||||
input("paper")
|
||||
input("alice's $900")
|
||||
output(CASH_PROGRAM_ID, "borrowed $900") { 900.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP }
|
||||
output(Cash.PROGRAM_ID, "borrowed $900") { 900.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP }
|
||||
output(thisTest.getContract(), "alice's paper") { "paper".output<ICommercialPaperState>().withOwner(ALICE) }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
command(MEGA_CORP_PUBKEY) { thisTest.getMoveCommand() }
|
||||
@ -129,8 +129,8 @@ class CommercialPaperTestsGeneric {
|
||||
input("some profits")
|
||||
|
||||
fun TransactionDSL<TransactionDSLInterpreter>.outputs(aliceGetsBack: Amount<Issued<Currency>>) {
|
||||
output(CASH_PROGRAM_ID, "Alice's profit") { aliceGetsBack.STATE `owned by` ALICE }
|
||||
output(CASH_PROGRAM_ID, "Change") { (someProfits - aliceGetsBack).STATE `owned by` MEGA_CORP }
|
||||
output(Cash.PROGRAM_ID, "Alice's profit") { aliceGetsBack.STATE `owned by` ALICE }
|
||||
output(Cash.PROGRAM_ID, "Change") { (someProfits - aliceGetsBack).STATE `owned by` MEGA_CORP }
|
||||
}
|
||||
|
||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||
|
@ -84,34 +84,34 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun trivial() {
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
|
||||
tweak {
|
||||
output(CASH_PROGRAM_ID) { outState.copy(amount = 2000.DOLLARS `issued by` defaultIssuer) }
|
||||
output(Cash.PROGRAM_ID) { outState.copy(amount = 2000.DOLLARS `issued by` defaultIssuer) }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
tweak {
|
||||
output(CASH_PROGRAM_ID) { outState }
|
||||
output(Cash.PROGRAM_ID) { outState }
|
||||
command(ALICE_PUBKEY) { DummyCommandData }
|
||||
// Invalid command
|
||||
this `fails with` "required net.corda.finance.contracts.asset.Cash.Commands.Move command"
|
||||
}
|
||||
tweak {
|
||||
output(CASH_PROGRAM_ID) { outState }
|
||||
output(Cash.PROGRAM_ID) { outState }
|
||||
command(BOB_PUBKEY) { Cash.Commands.Move() }
|
||||
this `fails with` "the owning keys are a subset of the signing keys"
|
||||
}
|
||||
tweak {
|
||||
output(CASH_PROGRAM_ID) { outState }
|
||||
output(CASH_PROGRAM_ID) { outState `issued by` MINI_CORP }
|
||||
output(Cash.PROGRAM_ID) { outState }
|
||||
output(Cash.PROGRAM_ID) { outState `issued by` MINI_CORP }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
this `fails with` "at least one cash input"
|
||||
}
|
||||
// Simple reallocation works.
|
||||
tweak {
|
||||
output(CASH_PROGRAM_ID) { outState }
|
||||
output(Cash.PROGRAM_ID) { outState }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
@ -122,9 +122,9 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
fun `issue by move`() {
|
||||
// Check we can't "move" money into existence.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { DummyState() }
|
||||
output(CASH_PROGRAM_ID) { outState }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { DummyState() }
|
||||
output(Cash.PROGRAM_ID) { outState }
|
||||
command(MINI_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||
|
||||
this `fails with` "there is at least one cash input for this group"
|
||||
@ -136,14 +136,14 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
// Check we can issue money only as long as the issuer institution is a command signer, i.e. any recognised
|
||||
// institution is allowed to issue as much cash as they want.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
output(CASH_PROGRAM_ID) { outState }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
output(Cash.PROGRAM_ID) { outState }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Issue() }
|
||||
this `fails with` "output states are issued by a command signer"
|
||||
}
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
output(CASH_PROGRAM_ID) {
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
output(Cash.PROGRAM_ID) {
|
||||
Cash.State(
|
||||
amount = 1000.DOLLARS `issued by` MINI_CORP.ref(12, 34),
|
||||
owner = AnonymousParty(ALICE_PUBKEY)
|
||||
@ -186,9 +186,9 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
fun `extended issue examples`() {
|
||||
// We can consume $1000 in a transaction and output $2000 as long as it's signed by an issuer.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { issuerInState }
|
||||
output(CASH_PROGRAM_ID) { inState.copy(amount = inState.amount * 2) }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { issuerInState }
|
||||
output(Cash.PROGRAM_ID) { inState.copy(amount = inState.amount * 2) }
|
||||
|
||||
// Move fails: not allowed to summon money.
|
||||
tweak {
|
||||
@ -205,27 +205,27 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
|
||||
// Can't use an issue command to lower the amount.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
output(CASH_PROGRAM_ID) { inState.copy(amount = inState.amount.splitEvenly(2).first()) }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
output(Cash.PROGRAM_ID) { inState.copy(amount = inState.amount.splitEvenly(2).first()) }
|
||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Issue() }
|
||||
this `fails with` "output values sum to more than the inputs"
|
||||
}
|
||||
|
||||
// Can't have an issue command that doesn't actually issue money.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
output(CASH_PROGRAM_ID) { inState }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
output(Cash.PROGRAM_ID) { inState }
|
||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Issue() }
|
||||
this `fails with` "output values sum to more than the inputs"
|
||||
}
|
||||
|
||||
// Can't have any other commands if we have an issue command (because the issue command overrules them)
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
output(CASH_PROGRAM_ID) { inState.copy(amount = inState.amount * 2) }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
output(Cash.PROGRAM_ID) { inState.copy(amount = inState.amount * 2) }
|
||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Issue() }
|
||||
tweak {
|
||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Issue() }
|
||||
@ -258,27 +258,27 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
fun testMergeSplit() {
|
||||
// Splitting value works.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
tweak {
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
val splits4 = inState.amount.splitEvenly(4)
|
||||
for (i in 0..3) output(CASH_PROGRAM_ID) { inState.copy(amount = splits4[i]) }
|
||||
for (i in 0..3) output(Cash.PROGRAM_ID) { inState.copy(amount = splits4[i]) }
|
||||
this.verifies()
|
||||
}
|
||||
// Merging 4 inputs into 2 outputs works.
|
||||
tweak {
|
||||
val splits2 = inState.amount.splitEvenly(2)
|
||||
val splits4 = inState.amount.splitEvenly(4)
|
||||
for (i in 0..3) input(CASH_PROGRAM_ID) { inState.copy(amount = splits4[i]) }
|
||||
for (i in 0..1) output(CASH_PROGRAM_ID) { inState.copy(amount = splits2[i]) }
|
||||
for (i in 0..3) input(Cash.PROGRAM_ID) { inState.copy(amount = splits4[i]) }
|
||||
for (i in 0..1) output(Cash.PROGRAM_ID) { inState.copy(amount = splits2[i]) }
|
||||
this.verifies()
|
||||
}
|
||||
// Merging 2 inputs into 1 works.
|
||||
tweak {
|
||||
val splits2 = inState.amount.splitEvenly(2)
|
||||
for (i in 0..1) input(CASH_PROGRAM_ID) { inState.copy(amount = splits2[i]) }
|
||||
output(CASH_PROGRAM_ID) { inState }
|
||||
for (i in 0..1) input(Cash.PROGRAM_ID) { inState.copy(amount = splits2[i]) }
|
||||
output(Cash.PROGRAM_ID) { inState }
|
||||
this.verifies()
|
||||
}
|
||||
}
|
||||
@ -287,17 +287,17 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun zeroSizedValues() {
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
input(CASH_PROGRAM_ID) { inState.copy(amount = 0.DOLLARS `issued by` defaultIssuer) }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
input(Cash.PROGRAM_ID) { inState.copy(amount = 0.DOLLARS `issued by` defaultIssuer) }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
this `fails with` "zero sized inputs"
|
||||
}
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
output(CASH_PROGRAM_ID) { inState }
|
||||
output(CASH_PROGRAM_ID) { inState.copy(amount = 0.DOLLARS `issued by` defaultIssuer) }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
output(Cash.PROGRAM_ID) { inState }
|
||||
output(Cash.PROGRAM_ID) { inState.copy(amount = 0.DOLLARS `issued by` defaultIssuer) }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
this `fails with` "zero sized outputs"
|
||||
}
|
||||
@ -307,58 +307,58 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
fun trivialMismatches() {
|
||||
// Can't change issuer.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
output(CASH_PROGRAM_ID) { outState `issued by` MINI_CORP }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
output(Cash.PROGRAM_ID) { outState `issued by` MINI_CORP }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
// Can't change deposit reference when splitting.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
val splits2 = inState.amount.splitEvenly(2)
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
for (i in 0..1) output(CASH_PROGRAM_ID) { outState.copy(amount = splits2[i]).editDepositRef(i.toByte()) }
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
for (i in 0..1) output(Cash.PROGRAM_ID) { outState.copy(amount = splits2[i]).editDepositRef(i.toByte()) }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
// Can't mix currencies.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
output(CASH_PROGRAM_ID) { outState.copy(amount = 800.DOLLARS `issued by` defaultIssuer) }
|
||||
output(CASH_PROGRAM_ID) { outState.copy(amount = 200.POUNDS `issued by` defaultIssuer) }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
output(Cash.PROGRAM_ID) { outState.copy(amount = 800.DOLLARS `issued by` defaultIssuer) }
|
||||
output(Cash.PROGRAM_ID) { outState.copy(amount = 200.POUNDS `issued by` defaultIssuer) }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
input(CASH_PROGRAM_ID) {
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
input(Cash.PROGRAM_ID) {
|
||||
inState.copy(
|
||||
amount = 150.POUNDS `issued by` defaultIssuer,
|
||||
owner = AnonymousParty(BOB_PUBKEY)
|
||||
)
|
||||
}
|
||||
output(CASH_PROGRAM_ID) { outState.copy(amount = 1150.DOLLARS `issued by` defaultIssuer) }
|
||||
output(Cash.PROGRAM_ID) { outState.copy(amount = 1150.DOLLARS `issued by` defaultIssuer) }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
// Can't have superfluous input states from different issuers.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
input(CASH_PROGRAM_ID) { inState `issued by` MINI_CORP }
|
||||
output(CASH_PROGRAM_ID) { outState }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
input(Cash.PROGRAM_ID) { inState `issued by` MINI_CORP }
|
||||
output(Cash.PROGRAM_ID) { outState }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
// Can't combine two different deposits at the same issuer.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
input(CASH_PROGRAM_ID) { inState.editDepositRef(3) }
|
||||
output(CASH_PROGRAM_ID) { outState.copy(amount = inState.amount * 2).editDepositRef(3) }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
input(Cash.PROGRAM_ID) { inState.editDepositRef(3) }
|
||||
output(Cash.PROGRAM_ID) { outState.copy(amount = inState.amount * 2).editDepositRef(3) }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
this `fails with` "for reference [01]"
|
||||
}
|
||||
@ -368,9 +368,9 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
fun exitLedger() {
|
||||
// Single input/output straightforward case.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { issuerInState }
|
||||
output(CASH_PROGRAM_ID) { issuerInState.copy(amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer)) }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { issuerInState }
|
||||
output(Cash.PROGRAM_ID) { issuerInState.copy(amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer)) }
|
||||
|
||||
tweak {
|
||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Exit(100.DOLLARS `issued by` defaultIssuer) }
|
||||
@ -394,12 +394,12 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
fun `exit ledger with multiple issuers`() {
|
||||
// Multi-issuer case.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { issuerInState }
|
||||
input(CASH_PROGRAM_ID) { issuerInState.copy(owner = MINI_CORP) `issued by` MINI_CORP }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { issuerInState }
|
||||
input(Cash.PROGRAM_ID) { issuerInState.copy(owner = MINI_CORP) `issued by` MINI_CORP }
|
||||
|
||||
output(CASH_PROGRAM_ID) { issuerInState.copy(amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer)) `issued by` MINI_CORP }
|
||||
output(CASH_PROGRAM_ID) { issuerInState.copy(owner = MINI_CORP, amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer)) }
|
||||
output(Cash.PROGRAM_ID) { issuerInState.copy(amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer)) `issued by` MINI_CORP }
|
||||
output(Cash.PROGRAM_ID) { issuerInState.copy(owner = MINI_CORP, amount = issuerInState.amount - (200.DOLLARS `issued by` defaultIssuer)) }
|
||||
|
||||
command(MEGA_CORP_PUBKEY, MINI_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||
|
||||
@ -417,9 +417,9 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
fun `exit cash not held by its issuer`() {
|
||||
// Single input/output straightforward case.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
output(CASH_PROGRAM_ID) { outState.copy(amount = inState.amount - (200.DOLLARS `issued by` defaultIssuer)) }
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
output(Cash.PROGRAM_ID) { outState.copy(amount = inState.amount - (200.DOLLARS `issued by` defaultIssuer)) }
|
||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Exit(200.DOLLARS `issued by` defaultIssuer) }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
@ -429,27 +429,27 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
@Test
|
||||
fun multiIssuer() {
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
// Gather 2000 dollars from two different issuers.
|
||||
input(CASH_PROGRAM_ID) { inState }
|
||||
input(CASH_PROGRAM_ID) { inState `issued by` MINI_CORP }
|
||||
input(Cash.PROGRAM_ID) { inState }
|
||||
input(Cash.PROGRAM_ID) { inState `issued by` MINI_CORP }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
|
||||
// Can't merge them together.
|
||||
tweak {
|
||||
output(CASH_PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY), amount = 2000.DOLLARS `issued by` defaultIssuer) }
|
||||
output(Cash.PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY), amount = 2000.DOLLARS `issued by` defaultIssuer) }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
// Missing MiniCorp deposit
|
||||
tweak {
|
||||
output(CASH_PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY)) }
|
||||
output(CASH_PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY)) }
|
||||
output(Cash.PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY)) }
|
||||
output(Cash.PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY)) }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
|
||||
// This works.
|
||||
output(CASH_PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY)) }
|
||||
output(CASH_PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY)) `issued by` MINI_CORP }
|
||||
output(Cash.PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY)) }
|
||||
output(Cash.PROGRAM_ID) { inState.copy(owner = AnonymousParty(BOB_PUBKEY)) `issued by` MINI_CORP }
|
||||
this.verifies()
|
||||
}
|
||||
}
|
||||
@ -458,12 +458,12 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
fun multiCurrency() {
|
||||
// Check we can do an atomic currency trade tx.
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
val pounds = Cash.State(658.POUNDS `issued by` MINI_CORP.ref(3, 4, 5), AnonymousParty(BOB_PUBKEY))
|
||||
input(CASH_PROGRAM_ID) { inState `owned by` AnonymousParty(ALICE_PUBKEY) }
|
||||
input(CASH_PROGRAM_ID) { pounds }
|
||||
output(CASH_PROGRAM_ID) { inState `owned by` AnonymousParty(BOB_PUBKEY) }
|
||||
output(CASH_PROGRAM_ID) { pounds `owned by` AnonymousParty(ALICE_PUBKEY) }
|
||||
input(Cash.PROGRAM_ID) { inState `owned by` AnonymousParty(ALICE_PUBKEY) }
|
||||
input(Cash.PROGRAM_ID) { pounds }
|
||||
output(Cash.PROGRAM_ID) { inState `owned by` AnonymousParty(BOB_PUBKEY) }
|
||||
output(Cash.PROGRAM_ID) { pounds `owned by` AnonymousParty(ALICE_PUBKEY) }
|
||||
command(ALICE_PUBKEY, BOB_PUBKEY) { Cash.Commands.Move() }
|
||||
|
||||
this.verifies()
|
||||
@ -482,7 +482,7 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
|
||||
fun makeCash(amount: Amount<Currency>, corp: Party, depositRef: Byte = 1) =
|
||||
StateAndRef(
|
||||
TransactionState<Cash.State>(Cash.State(amount `issued by` corp.ref(depositRef), OUR_IDENTITY_1), CASH_PROGRAM_ID, DUMMY_NOTARY),
|
||||
TransactionState<Cash.State>(Cash.State(amount `issued by` corp.ref(depositRef), OUR_IDENTITY_1), Cash.PROGRAM_ID, DUMMY_NOTARY),
|
||||
StateRef(SecureHash.randomSHA256(), Random().nextInt(32))
|
||||
)
|
||||
|
||||
@ -787,8 +787,8 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
|
||||
ledger(mockService) {
|
||||
unverifiedTransaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
output(CASH_PROGRAM_ID, "MEGA_CORP cash") {
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
output(Cash.PROGRAM_ID, "MEGA_CORP cash") {
|
||||
Cash.State(
|
||||
amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
|
||||
owner = MEGA_CORP
|
||||
@ -797,19 +797,19 @@ class CashTests : TestDependencyInjectionBase() {
|
||||
}
|
||||
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input("MEGA_CORP cash")
|
||||
output(CASH_PROGRAM_ID, "MEGA_CORP cash 2", "MEGA_CORP cash".output<Cash.State>().copy(owner = AnonymousParty(ALICE_PUBKEY)) )
|
||||
output(Cash.PROGRAM_ID, "MEGA_CORP cash 2", "MEGA_CORP cash".output<Cash.State>().copy(owner = AnonymousParty(ALICE_PUBKEY)) )
|
||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
tweak {
|
||||
transaction {
|
||||
attachment(CASH_PROGRAM_ID)
|
||||
attachment(Cash.PROGRAM_ID)
|
||||
input("MEGA_CORP cash")
|
||||
// We send it to another pubkey so that the transaction is not identical to the previous one
|
||||
output(CASH_PROGRAM_ID, "MEGA_CORP cash 3", "MEGA_CORP cash".output<Cash.State>().copy(owner = ALICE))
|
||||
output(Cash.PROGRAM_ID, "MEGA_CORP cash 3", "MEGA_CORP cash".output<Cash.State>().copy(owner = ALICE))
|
||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
package net.corda.finance.contracts.asset
|
||||
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.NullKeys.NULL_PARTY
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.sha256
|
||||
import net.corda.core.crypto.NullKeys.NULL_PARTY
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.AnonymousParty
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
@ -16,7 +16,7 @@ import net.corda.finance.contracts.Commodity
|
||||
import net.corda.finance.contracts.NetType
|
||||
import net.corda.finance.contracts.asset.Obligation.Lifecycle
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.contracts.DummyState
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.After
|
||||
@ -56,11 +56,11 @@ class ObligationTests {
|
||||
group: LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter>
|
||||
) = group.apply {
|
||||
unverifiedTransaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
output(OBLIGATION_PROGRAM_ID, "Alice's $1,000,000 obligation to Bob", oneMillionDollars.OBLIGATION between Pair(ALICE, BOB))
|
||||
output(OBLIGATION_PROGRAM_ID, "Bob's $1,000,000 obligation to Alice", oneMillionDollars.OBLIGATION between Pair(BOB, ALICE))
|
||||
output(OBLIGATION_PROGRAM_ID, "MegaCorp's $1,000,000 obligation to Bob", oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, BOB))
|
||||
output(OBLIGATION_PROGRAM_ID, "Alice's $1,000,000", 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
output(Obligation.PROGRAM_ID, "Alice's $1,000,000 obligation to Bob", oneMillionDollars.OBLIGATION between Pair(ALICE, BOB))
|
||||
output(Obligation.PROGRAM_ID, "Bob's $1,000,000 obligation to Alice", oneMillionDollars.OBLIGATION between Pair(BOB, ALICE))
|
||||
output(Obligation.PROGRAM_ID, "MegaCorp's $1,000,000 obligation to Bob", oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, BOB))
|
||||
output(Obligation.PROGRAM_ID, "Alice's $1,000,000", 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE)
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,34 +72,34 @@ class ObligationTests {
|
||||
@Test
|
||||
fun trivial() {
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
|
||||
tweak {
|
||||
output(OBLIGATION_PROGRAM_ID) { outState.copy(quantity = 2000.DOLLARS.quantity) }
|
||||
output(Obligation.PROGRAM_ID) { outState.copy(quantity = 2000.DOLLARS.quantity) }
|
||||
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
tweak {
|
||||
output(OBLIGATION_PROGRAM_ID) { outState }
|
||||
output(Obligation.PROGRAM_ID) { outState }
|
||||
command(CHARLIE.owningKey) { DummyCommandData }
|
||||
// Invalid command
|
||||
this `fails with` "required net.corda.finance.contracts.asset.Obligation.Commands.Move command"
|
||||
}
|
||||
tweak {
|
||||
output(OBLIGATION_PROGRAM_ID) { outState }
|
||||
output(Obligation.PROGRAM_ID) { outState }
|
||||
command(BOB_PUBKEY) { Obligation.Commands.Move() }
|
||||
this `fails with` "the owning keys are a subset of the signing keys"
|
||||
}
|
||||
tweak {
|
||||
output(OBLIGATION_PROGRAM_ID) { outState }
|
||||
output(OBLIGATION_PROGRAM_ID) { outState `issued by` MINI_CORP }
|
||||
output(Obligation.PROGRAM_ID) { outState }
|
||||
output(Obligation.PROGRAM_ID) { outState `issued by` MINI_CORP }
|
||||
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
|
||||
this `fails with` "at least one obligation input"
|
||||
}
|
||||
// Simple reallocation works.
|
||||
tweak {
|
||||
output(OBLIGATION_PROGRAM_ID) { outState }
|
||||
output(Obligation.PROGRAM_ID) { outState }
|
||||
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
@ -110,9 +110,9 @@ class ObligationTests {
|
||||
fun `issue debt`() {
|
||||
// Check we can't "move" debt into existence.
|
||||
transaction {
|
||||
attachments(DUMMY_PROGRAM_ID, OBLIGATION_PROGRAM_ID)
|
||||
input(DUMMY_PROGRAM_ID) { DummyState() }
|
||||
output(OBLIGATION_PROGRAM_ID) { outState }
|
||||
attachments(DummyContract.PROGRAM_ID, Obligation.PROGRAM_ID)
|
||||
input(DummyContract.PROGRAM_ID) { DummyState() }
|
||||
output(Obligation.PROGRAM_ID) { outState }
|
||||
command(MINI_CORP_PUBKEY) { Obligation.Commands.Move() }
|
||||
|
||||
this `fails with` "at least one obligation input"
|
||||
@ -121,14 +121,14 @@ class ObligationTests {
|
||||
// Check we can issue money only as long as the issuer institution is a command signer, i.e. any recognised
|
||||
// institution is allowed to issue as much cash as they want.
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
output(OBLIGATION_PROGRAM_ID) { outState }
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
output(Obligation.PROGRAM_ID) { outState }
|
||||
command(CHARLIE.owningKey) { Obligation.Commands.Issue() }
|
||||
this `fails with` "output states are issued by a command signer"
|
||||
}
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
output(OBLIGATION_PROGRAM_ID) {
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
output(Obligation.PROGRAM_ID) {
|
||||
Obligation.State(
|
||||
obligor = MINI_CORP,
|
||||
quantity = 1000.DOLLARS.quantity,
|
||||
@ -160,9 +160,9 @@ class ObligationTests {
|
||||
|
||||
// We can consume $1000 in a transaction and output $2000 as long as it's signed by an issuer.
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
output(OBLIGATION_PROGRAM_ID) { inState.copy(quantity = inState.amount.quantity * 2) }
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
output(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.amount.quantity * 2) }
|
||||
|
||||
// Move fails: not allowed to summon money.
|
||||
tweak {
|
||||
@ -179,27 +179,27 @@ class ObligationTests {
|
||||
|
||||
// Can't use an issue command to lower the amount.
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
output(OBLIGATION_PROGRAM_ID) { inState.copy(quantity = inState.amount.quantity / 2) }
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
output(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.amount.quantity / 2) }
|
||||
command(MEGA_CORP_PUBKEY) { Obligation.Commands.Issue() }
|
||||
this `fails with` "output values sum to more than the inputs"
|
||||
}
|
||||
|
||||
// Can't have an issue command that doesn't actually issue money.
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
output(OBLIGATION_PROGRAM_ID) { inState }
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
output(Obligation.PROGRAM_ID) { inState }
|
||||
command(MEGA_CORP_PUBKEY) { Obligation.Commands.Issue() }
|
||||
this `fails with` ""
|
||||
}
|
||||
|
||||
// Can't have any other commands if we have an issue command (because the issue command overrules them).
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
output(OBLIGATION_PROGRAM_ID) { inState.copy(quantity = inState.amount.quantity * 2) }
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
output(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.amount.quantity * 2) }
|
||||
command(MEGA_CORP_PUBKEY) { Obligation.Commands.Issue() }
|
||||
tweak {
|
||||
command(MEGA_CORP_PUBKEY) { Obligation.Commands.Issue() }
|
||||
@ -234,8 +234,8 @@ class ObligationTests {
|
||||
@Test
|
||||
fun `generate close-out net transaction`() {
|
||||
initialiseTestSerialization()
|
||||
val obligationAliceToBob = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB), OBLIGATION_PROGRAM_ID)
|
||||
val obligationBobToAlice = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(BOB, ALICE), OBLIGATION_PROGRAM_ID)
|
||||
val obligationAliceToBob = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB), Obligation.PROGRAM_ID)
|
||||
val obligationBobToAlice = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(BOB, ALICE), Obligation.PROGRAM_ID)
|
||||
val tx = TransactionBuilder(DUMMY_NOTARY).apply {
|
||||
Obligation<Currency>().generateCloseOutNetting(this, ALICE, obligationAliceToBob, obligationBobToAlice)
|
||||
}.toWireTransaction(miniCorpServices)
|
||||
@ -246,8 +246,8 @@ class ObligationTests {
|
||||
@Test
|
||||
fun `generate close-out net transaction with remainder`() {
|
||||
initialiseTestSerialization()
|
||||
val obligationAliceToBob = getStateAndRef((2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(ALICE, BOB), OBLIGATION_PROGRAM_ID)
|
||||
val obligationBobToAlice = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(BOB, ALICE), OBLIGATION_PROGRAM_ID)
|
||||
val obligationAliceToBob = getStateAndRef((2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(ALICE, BOB), Obligation.PROGRAM_ID)
|
||||
val obligationBobToAlice = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(BOB, ALICE), Obligation.PROGRAM_ID)
|
||||
val tx = TransactionBuilder(DUMMY_NOTARY).apply {
|
||||
Obligation<Currency>().generateCloseOutNetting(this, ALICE, obligationAliceToBob, obligationBobToAlice)
|
||||
}.toWireTransaction(miniCorpServices)
|
||||
@ -261,8 +261,8 @@ class ObligationTests {
|
||||
@Test
|
||||
fun `generate payment net transaction`() {
|
||||
initialiseTestSerialization()
|
||||
val obligationAliceToBob = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB), OBLIGATION_PROGRAM_ID)
|
||||
val obligationBobToAlice = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(BOB, ALICE), OBLIGATION_PROGRAM_ID)
|
||||
val obligationAliceToBob = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB), Obligation.PROGRAM_ID)
|
||||
val obligationBobToAlice = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(BOB, ALICE), Obligation.PROGRAM_ID)
|
||||
val tx = TransactionBuilder(DUMMY_NOTARY).apply {
|
||||
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBob.state.data.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice)
|
||||
}.toWireTransaction(miniCorpServices)
|
||||
@ -273,9 +273,9 @@ class ObligationTests {
|
||||
@Test
|
||||
fun `generate payment net transaction with remainder`() {
|
||||
initialiseTestSerialization()
|
||||
val obligationAliceToBob = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB), OBLIGATION_PROGRAM_ID)
|
||||
val obligationAliceToBob = getStateAndRef(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB), Obligation.PROGRAM_ID)
|
||||
val obligationAliceToBobState = obligationAliceToBob.state.data
|
||||
val obligationBobToAlice = getStateAndRef((2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(BOB, ALICE), OBLIGATION_PROGRAM_ID)
|
||||
val obligationBobToAlice = getStateAndRef((2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(BOB, ALICE), Obligation.PROGRAM_ID)
|
||||
val obligationBobToAliceState = obligationBobToAlice.state.data
|
||||
val tx = TransactionBuilder(DUMMY_NOTARY).apply {
|
||||
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBobState.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice)
|
||||
@ -359,7 +359,7 @@ class ObligationTests {
|
||||
ledger(mockService) {
|
||||
cashObligationTestRoots(this)
|
||||
transaction("Issuance") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input("Alice's $1,000,000 obligation to Bob")
|
||||
input("Bob's $1,000,000 obligation to Alice")
|
||||
// Note we can sign with either key here
|
||||
@ -375,11 +375,11 @@ class ObligationTests {
|
||||
ledger(mockService) {
|
||||
cashObligationTestRoots(this)
|
||||
transaction("Issuance") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
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(OBLIGATION_PROGRAM_ID, "change") { oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, BOB) }
|
||||
output(Obligation.PROGRAM_ID, "change") { oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, BOB) }
|
||||
command(BOB_PUBKEY, MEGA_CORP_PUBKEY) { Obligation.Commands.Net(NetType.CLOSE_OUT) }
|
||||
timeWindow(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
@ -391,10 +391,10 @@ class ObligationTests {
|
||||
ledger {
|
||||
cashObligationTestRoots(this)
|
||||
transaction("Issuance") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input("Alice's $1,000,000 obligation to Bob")
|
||||
input("Bob's $1,000,000 obligation to Alice")
|
||||
output(OBLIGATION_PROGRAM_ID, "change") { (oneMillionDollars.splitEvenly(2).first()).OBLIGATION between Pair(ALICE, BOB) }
|
||||
output(Obligation.PROGRAM_ID, "change") { (oneMillionDollars.splitEvenly(2).first()).OBLIGATION between Pair(ALICE, BOB) }
|
||||
command(BOB_PUBKEY) { Obligation.Commands.Net(NetType.CLOSE_OUT) }
|
||||
timeWindow(TEST_TX_TIME)
|
||||
this `fails with` "amounts owed on input and output must match"
|
||||
@ -405,7 +405,7 @@ class ObligationTests {
|
||||
ledger {
|
||||
cashObligationTestRoots(this)
|
||||
transaction("Issuance") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input("Alice's $1,000,000 obligation to Bob")
|
||||
input("Bob's $1,000,000 obligation to Alice")
|
||||
command(MEGA_CORP_PUBKEY) { Obligation.Commands.Net(NetType.CLOSE_OUT) }
|
||||
@ -421,7 +421,7 @@ class ObligationTests {
|
||||
ledger(mockService) {
|
||||
cashObligationTestRoots(this)
|
||||
transaction("Issuance") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input("Alice's $1,000,000 obligation to Bob")
|
||||
input("Bob's $1,000,000 obligation to Alice")
|
||||
command(ALICE_PUBKEY, BOB_PUBKEY) { Obligation.Commands.Net(NetType.PAYMENT) }
|
||||
@ -436,7 +436,7 @@ class ObligationTests {
|
||||
ledger {
|
||||
cashObligationTestRoots(this)
|
||||
transaction("Issuance") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input("Alice's $1,000,000 obligation to Bob")
|
||||
input("Bob's $1,000,000 obligation to Alice")
|
||||
command(BOB_PUBKEY) { Obligation.Commands.Net(NetType.PAYMENT) }
|
||||
@ -449,10 +449,10 @@ class ObligationTests {
|
||||
ledger(mockService) {
|
||||
cashObligationTestRoots(this)
|
||||
transaction("Issuance") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input("Bob's $1,000,000 obligation to Alice")
|
||||
input("MegaCorp's $1,000,000 obligation to Bob")
|
||||
output(OBLIGATION_PROGRAM_ID, "MegaCorp's $1,000,000 obligation to Alice") { oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, ALICE) }
|
||||
output(Obligation.PROGRAM_ID, "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) }
|
||||
timeWindow(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
@ -464,10 +464,10 @@ class ObligationTests {
|
||||
ledger(mockService) {
|
||||
cashObligationTestRoots(this)
|
||||
transaction("Issuance") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input("Bob's $1,000,000 obligation to Alice")
|
||||
input("MegaCorp's $1,000,000 obligation to Bob")
|
||||
output(OBLIGATION_PROGRAM_ID, "MegaCorp's $1,000,000 obligation to Alice") { oneMillionDollars.OBLIGATION between Pair(MEGA_CORP, ALICE) }
|
||||
output(Obligation.PROGRAM_ID, "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) }
|
||||
timeWindow(TEST_TX_TIME)
|
||||
this `fails with` "all involved parties have signed"
|
||||
@ -481,10 +481,10 @@ class ObligationTests {
|
||||
ledger {
|
||||
cashObligationTestRoots(this)
|
||||
transaction("Settlement") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input("Alice's $1,000,000 obligation to Bob")
|
||||
input("Alice's $1,000,000")
|
||||
output(OBLIGATION_PROGRAM_ID, "Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB }
|
||||
output(Obligation.PROGRAM_ID, "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::class.java) }
|
||||
attachment(attachment(cashContractBytes.inputStream()))
|
||||
@ -496,11 +496,11 @@ class ObligationTests {
|
||||
val halfAMillionDollars = 500000.DOLLARS `issued by` defaultIssuer
|
||||
ledger {
|
||||
transaction("Settlement") {
|
||||
attachments(OBLIGATION_PROGRAM_ID, CASH_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID, oneMillionDollars.OBLIGATION between Pair(ALICE, BOB))
|
||||
input(CASH_PROGRAM_ID, 500000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE)
|
||||
output(OBLIGATION_PROGRAM_ID, "Alice's $500,000 obligation to Bob") { halfAMillionDollars.OBLIGATION between Pair(ALICE, BOB) }
|
||||
output(OBLIGATION_PROGRAM_ID, "Bob's $500,000") { 500000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB }
|
||||
attachments(Obligation.PROGRAM_ID, Cash.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID, oneMillionDollars.OBLIGATION between Pair(ALICE, BOB))
|
||||
input(Cash.PROGRAM_ID, 500000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE)
|
||||
output(Obligation.PROGRAM_ID, "Alice's $500,000 obligation to Bob") { halfAMillionDollars.OBLIGATION between Pair(ALICE, BOB) }
|
||||
output(Obligation.PROGRAM_ID, "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::class.java) }
|
||||
attachment(attachment(cashContractBytes.inputStream()))
|
||||
@ -512,10 +512,10 @@ class ObligationTests {
|
||||
val defaultedObligation: Obligation.State<Currency> = (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)).copy(lifecycle = Lifecycle.DEFAULTED)
|
||||
ledger {
|
||||
transaction("Settlement") {
|
||||
attachments(OBLIGATION_PROGRAM_ID, CASH_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID, defaultedObligation) // Alice's defaulted $1,000,000 obligation to Bob
|
||||
input(CASH_PROGRAM_ID, 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE)
|
||||
output(OBLIGATION_PROGRAM_ID, "Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB }
|
||||
attachments(Obligation.PROGRAM_ID, Cash.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID, defaultedObligation) // Alice's defaulted $1,000,000 obligation to Bob
|
||||
input(Cash.PROGRAM_ID, 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE)
|
||||
output(Obligation.PROGRAM_ID, "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::class.java) }
|
||||
this `fails with` "all inputs are in the normal state"
|
||||
@ -526,10 +526,10 @@ class ObligationTests {
|
||||
ledger {
|
||||
cashObligationTestRoots(this)
|
||||
transaction("Settlement") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input("Alice's $1,000,000 obligation to Bob")
|
||||
input("Alice's $1,000,000")
|
||||
output(OBLIGATION_PROGRAM_ID, "Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB }
|
||||
output(Obligation.PROGRAM_ID, "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::class.java) }
|
||||
attachment(attachment(cashContractBytes.inputStream()))
|
||||
@ -549,15 +549,15 @@ class ObligationTests {
|
||||
// Try settling a simple commodity obligation
|
||||
ledger {
|
||||
unverifiedTransaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
output(OBLIGATION_PROGRAM_ID, "Alice's 1 FCOJ obligation to Bob", oneUnitFcojObligation between Pair(ALICE, BOB))
|
||||
output(OBLIGATION_PROGRAM_ID, "Alice's 1 FCOJ", CommodityContract.State(oneUnitFcoj, ALICE))
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
output(Obligation.PROGRAM_ID, "Alice's 1 FCOJ obligation to Bob", oneUnitFcojObligation between Pair(ALICE, BOB))
|
||||
output(Obligation.PROGRAM_ID, "Alice's 1 FCOJ", CommodityContract.State(oneUnitFcoj, ALICE))
|
||||
}
|
||||
transaction("Settlement") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input("Alice's 1 FCOJ obligation to Bob")
|
||||
input("Alice's 1 FCOJ")
|
||||
output(OBLIGATION_PROGRAM_ID, "Bob's 1 FCOJ") { CommodityContract.State(oneUnitFcoj, BOB) }
|
||||
output(Obligation.PROGRAM_ID, "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::class.java) }
|
||||
attachment(attachment(commodityContractBytes.inputStream()))
|
||||
@ -572,9 +572,9 @@ class ObligationTests {
|
||||
ledger {
|
||||
cashObligationTestRoots(this)
|
||||
transaction("Settlement") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input("Alice's $1,000,000 obligation to Bob")
|
||||
output(OBLIGATION_PROGRAM_ID, "Alice's defaulted $1,000,000 obligation to Bob") { (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)).copy(lifecycle = Lifecycle.DEFAULTED) }
|
||||
output(Obligation.PROGRAM_ID, "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 time-window from the authority"
|
||||
}
|
||||
@ -584,9 +584,9 @@ class ObligationTests {
|
||||
val pastTestTime = TEST_TX_TIME - 7.days
|
||||
val futureTestTime = TEST_TX_TIME + 7.days
|
||||
transaction("Settlement") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID, oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` futureTestTime)
|
||||
output(OBLIGATION_PROGRAM_ID, "Alice's defaulted $1,000,000 obligation to Bob") { (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` futureTestTime).copy(lifecycle = Lifecycle.DEFAULTED) }
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID, oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` futureTestTime)
|
||||
output(Obligation.PROGRAM_ID, "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) }
|
||||
timeWindow(TEST_TX_TIME)
|
||||
this `fails with` "the due date has passed"
|
||||
@ -596,9 +596,9 @@ class ObligationTests {
|
||||
unsetCordappPackages()
|
||||
ledger {
|
||||
transaction("Settlement") {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID, oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` pastTestTime)
|
||||
output(OBLIGATION_PROGRAM_ID, "Alice's defaulted $1,000,000 obligation to Bob") { (oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` pastTestTime).copy(lifecycle = Lifecycle.DEFAULTED) }
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID, oneMillionDollars.OBLIGATION between Pair(ALICE, BOB) `at` pastTestTime)
|
||||
output(Obligation.PROGRAM_ID, "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) }
|
||||
timeWindow(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
@ -611,25 +611,25 @@ class ObligationTests {
|
||||
fun testMergeSplit() {
|
||||
// Splitting value works.
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
|
||||
tweak {
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
repeat(4) { output(OBLIGATION_PROGRAM_ID) { inState.copy(quantity = inState.quantity / 4) } }
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
repeat(4) { output(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.quantity / 4) } }
|
||||
this.verifies()
|
||||
}
|
||||
// Merging 4 inputs into 2 outputs works.
|
||||
tweak {
|
||||
repeat(4) { input(OBLIGATION_PROGRAM_ID) { inState.copy(quantity = inState.quantity / 4) } }
|
||||
output(OBLIGATION_PROGRAM_ID) { inState.copy(quantity = inState.quantity / 2) }
|
||||
output(OBLIGATION_PROGRAM_ID) { inState.copy(quantity = inState.quantity / 2) }
|
||||
repeat(4) { input(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.quantity / 4) } }
|
||||
output(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.quantity / 2) }
|
||||
output(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.quantity / 2) }
|
||||
this.verifies()
|
||||
}
|
||||
// Merging 2 inputs into 1 works.
|
||||
tweak {
|
||||
input(OBLIGATION_PROGRAM_ID) { inState.copy(quantity = inState.quantity / 2) }
|
||||
input(OBLIGATION_PROGRAM_ID) { inState.copy(quantity = inState.quantity / 2) }
|
||||
output(OBLIGATION_PROGRAM_ID) { inState }
|
||||
input(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.quantity / 2) }
|
||||
input(Obligation.PROGRAM_ID) { inState.copy(quantity = inState.quantity / 2) }
|
||||
output(Obligation.PROGRAM_ID) { inState }
|
||||
this.verifies()
|
||||
}
|
||||
}
|
||||
@ -638,18 +638,18 @@ class ObligationTests {
|
||||
@Test
|
||||
fun zeroSizedValues() {
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
|
||||
tweak {
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
input(OBLIGATION_PROGRAM_ID) { inState.copy(quantity = 0L) }
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
input(Obligation.PROGRAM_ID) { inState.copy(quantity = 0L) }
|
||||
|
||||
this `fails with` "zero sized inputs"
|
||||
}
|
||||
tweak {
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
output(OBLIGATION_PROGRAM_ID) { inState }
|
||||
output(OBLIGATION_PROGRAM_ID) { inState.copy(quantity = 0L) }
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
output(Obligation.PROGRAM_ID) { inState }
|
||||
output(Obligation.PROGRAM_ID) { inState.copy(quantity = 0L) }
|
||||
|
||||
this `fails with` "zero sized outputs"
|
||||
}
|
||||
@ -660,41 +660,41 @@ class ObligationTests {
|
||||
fun trivialMismatches() {
|
||||
// Can't change issuer.
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
output(OBLIGATION_PROGRAM_ID) { outState `issued by` MINI_CORP }
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
output(Obligation.PROGRAM_ID) { outState `issued by` MINI_CORP }
|
||||
command(MINI_CORP_PUBKEY) { Obligation.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
// Can't mix currencies.
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
output(OBLIGATION_PROGRAM_ID) { outState.copy(quantity = 80000, template = megaCorpDollarSettlement) }
|
||||
output(OBLIGATION_PROGRAM_ID) { outState.copy(quantity = 20000, template = megaCorpPoundSettlement) }
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
output(Obligation.PROGRAM_ID) { outState.copy(quantity = 80000, template = megaCorpDollarSettlement) }
|
||||
output(Obligation.PROGRAM_ID) { outState.copy(quantity = 20000, template = megaCorpPoundSettlement) }
|
||||
command(MINI_CORP_PUBKEY) { Obligation.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
input(OBLIGATION_PROGRAM_ID) {
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
input(Obligation.PROGRAM_ID) {
|
||||
inState.copy(
|
||||
quantity = 15000,
|
||||
template = megaCorpPoundSettlement,
|
||||
beneficiary = AnonymousParty(BOB_PUBKEY)
|
||||
)
|
||||
}
|
||||
output(OBLIGATION_PROGRAM_ID) { outState.copy(quantity = 115000) }
|
||||
output(Obligation.PROGRAM_ID) { outState.copy(quantity = 115000) }
|
||||
command(MINI_CORP_PUBKEY) { Obligation.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
// Can't have superfluous input states from different issuers.
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
input(OBLIGATION_PROGRAM_ID) { inState `issued by` MINI_CORP }
|
||||
output(OBLIGATION_PROGRAM_ID) { outState }
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
input(Obligation.PROGRAM_ID) { inState `issued by` MINI_CORP }
|
||||
output(Obligation.PROGRAM_ID) { outState }
|
||||
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
@ -704,9 +704,9 @@ class ObligationTests {
|
||||
fun `exit single product obligation`() {
|
||||
// Single input/output straightforward case.
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
output(OBLIGATION_PROGRAM_ID) { outState.copy(quantity = inState.quantity - 200.DOLLARS.quantity) }
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
output(Obligation.PROGRAM_ID) { outState.copy(quantity = inState.quantity - 200.DOLLARS.quantity) }
|
||||
|
||||
tweak {
|
||||
command(CHARLIE.owningKey) { Obligation.Commands.Exit(Amount(100.DOLLARS.quantity, inState.amount.token)) }
|
||||
@ -731,13 +731,13 @@ class ObligationTests {
|
||||
fun `exit multiple product obligations`() {
|
||||
// Multi-product case.
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
|
||||
input(OBLIGATION_PROGRAM_ID) { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedPounds)) }
|
||||
input(OBLIGATION_PROGRAM_ID) { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedDollars)) }
|
||||
input(Obligation.PROGRAM_ID) { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedPounds)) }
|
||||
input(Obligation.PROGRAM_ID) { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedDollars)) }
|
||||
|
||||
output(OBLIGATION_PROGRAM_ID) { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedPounds), quantity = inState.quantity - 200.POUNDS.quantity) }
|
||||
output(OBLIGATION_PROGRAM_ID) { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedDollars), quantity = inState.quantity - 200.DOLLARS.quantity) }
|
||||
output(Obligation.PROGRAM_ID) { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedPounds), quantity = inState.quantity - 200.POUNDS.quantity) }
|
||||
output(Obligation.PROGRAM_ID) { inState.copy(template = inState.template.copy(acceptableIssuedProducts = megaIssuedDollars), quantity = inState.quantity - 200.DOLLARS.quantity) }
|
||||
|
||||
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
|
||||
|
||||
@ -754,29 +754,29 @@ class ObligationTests {
|
||||
@Test
|
||||
fun multiIssuer() {
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
|
||||
// Gather 2000 dollars from two different issuers.
|
||||
input(OBLIGATION_PROGRAM_ID) { inState }
|
||||
input(OBLIGATION_PROGRAM_ID) { inState `issued by` MINI_CORP }
|
||||
input(Obligation.PROGRAM_ID) { inState }
|
||||
input(Obligation.PROGRAM_ID) { inState `issued by` MINI_CORP }
|
||||
|
||||
// Can't merge them together.
|
||||
tweak {
|
||||
output(OBLIGATION_PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY), quantity = 200000L) }
|
||||
output(Obligation.PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY), quantity = 200000L) }
|
||||
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
// Missing MiniCorp deposit
|
||||
tweak {
|
||||
output(OBLIGATION_PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) }
|
||||
output(OBLIGATION_PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) }
|
||||
output(Obligation.PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) }
|
||||
output(Obligation.PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) }
|
||||
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
|
||||
this `fails with` "the amounts balance"
|
||||
}
|
||||
|
||||
// This works.
|
||||
output(OBLIGATION_PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) }
|
||||
output(OBLIGATION_PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) `issued by` MINI_CORP }
|
||||
output(Obligation.PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) }
|
||||
output(Obligation.PROGRAM_ID) { inState.copy(beneficiary = AnonymousParty(BOB_PUBKEY)) `issued by` MINI_CORP }
|
||||
command(CHARLIE.owningKey) { Obligation.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
@ -786,12 +786,12 @@ class ObligationTests {
|
||||
fun multiCurrency() {
|
||||
// Check we can do an atomic currency trade tx.
|
||||
transaction {
|
||||
attachments(OBLIGATION_PROGRAM_ID)
|
||||
attachments(Obligation.PROGRAM_ID)
|
||||
val pounds = Obligation.State(Lifecycle.NORMAL, MINI_CORP, megaCorpPoundSettlement, 658.POUNDS.quantity, AnonymousParty(BOB_PUBKEY))
|
||||
input(OBLIGATION_PROGRAM_ID) { inState `owned by` CHARLIE }
|
||||
input(OBLIGATION_PROGRAM_ID) { pounds }
|
||||
output(OBLIGATION_PROGRAM_ID) { inState `owned by` AnonymousParty(BOB_PUBKEY) }
|
||||
output(OBLIGATION_PROGRAM_ID) { pounds `owned by` CHARLIE }
|
||||
input(Obligation.PROGRAM_ID) { inState `owned by` CHARLIE }
|
||||
input(Obligation.PROGRAM_ID) { pounds }
|
||||
output(Obligation.PROGRAM_ID) { inState `owned by` AnonymousParty(BOB_PUBKEY) }
|
||||
output(Obligation.PROGRAM_ID) { pounds `owned by` CHARLIE }
|
||||
command(CHARLIE.owningKey, BOB_PUBKEY) { Obligation.Commands.Move() }
|
||||
|
||||
this.verifies()
|
||||
|
@ -25,7 +25,6 @@ import net.corda.node.services.transactions.minCorrectReplicas
|
||||
import net.corda.node.utilities.ServiceIdentityGenerator
|
||||
import net.corda.nodeapi.internal.ServiceInfo
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.getDefaultNotary
|
||||
@ -77,7 +76,7 @@ class BFTNotaryServiceTests {
|
||||
val notary = node.services.getDefaultNotary()
|
||||
val f = node.run {
|
||||
val trivialTx = signInitialTransaction(notary) {
|
||||
addOutputState(DummyContract.SingleOwnerState(owner = info.chooseIdentity()), DUMMY_PROGRAM_ID, AlwaysAcceptAttachmentConstraint)
|
||||
addOutputState(DummyContract.SingleOwnerState(owner = info.chooseIdentity()), DummyContract.PROGRAM_ID, AlwaysAcceptAttachmentConstraint)
|
||||
}
|
||||
// Create a new consensus while the redundant replica is sleeping:
|
||||
services.startFlow(NotaryFlow.Client(trivialTx)).resultFuture
|
||||
@ -102,7 +101,7 @@ class BFTNotaryServiceTests {
|
||||
val notary = node.services.getDefaultNotary()
|
||||
node.run {
|
||||
val issueTx = signInitialTransaction(notary) {
|
||||
addOutputState(DummyContract.SingleOwnerState(owner = info.chooseIdentity()), DUMMY_PROGRAM_ID, AlwaysAcceptAttachmentConstraint)
|
||||
addOutputState(DummyContract.SingleOwnerState(owner = info.chooseIdentity()), DummyContract.PROGRAM_ID, AlwaysAcceptAttachmentConstraint)
|
||||
}
|
||||
database.transaction {
|
||||
services.recordTransactions(issueTx)
|
||||
|
@ -14,7 +14,8 @@ import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.node.services.transactions.RaftValidatingNotaryService
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.DUMMY_BANK_A
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.node.NodeBasedTest
|
||||
import org.junit.After
|
||||
@ -58,7 +59,7 @@ class RaftNotaryServiceTests : NodeBasedTest() {
|
||||
|
||||
val secondSpendBuilder = TransactionBuilder(notaryParty).withItems(inputState).run {
|
||||
val dummyState = DummyContract.SingleOwnerState(0, bankA.info.chooseIdentity())
|
||||
addOutputState(dummyState, DUMMY_PROGRAM_ID)
|
||||
addOutputState(dummyState, DummyContract.PROGRAM_ID)
|
||||
addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey))
|
||||
this
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.testing.BOB
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.aliceBobAndNotary
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.contracts.DummyState
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.dummyCommand
|
||||
@ -29,7 +29,7 @@ class LargeTransactionsTest {
|
||||
@Suspendable
|
||||
override fun call() {
|
||||
val tx = TransactionBuilder(notary = DUMMY_NOTARY)
|
||||
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
|
||||
.addOutputState(DummyState(), DummyContract.PROGRAM_ID)
|
||||
.addCommand(dummyCommand(ourIdentity.owningKey))
|
||||
.addAttachment(hash1)
|
||||
.addAttachment(hash2)
|
||||
|
@ -29,16 +29,19 @@ import net.corda.core.utilities.unwrap
|
||||
import net.corda.finance.DOLLARS
|
||||
import net.corda.finance.`issued by`
|
||||
import net.corda.finance.contracts.CommercialPaper
|
||||
import net.corda.finance.contracts.asset.*
|
||||
import net.corda.finance.contracts.asset.CASH
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.contracts.asset.`issued by`
|
||||
import net.corda.finance.contracts.asset.`owned by`
|
||||
import net.corda.finance.flows.TwoPartyTradeFlow.Buyer
|
||||
import net.corda.finance.flows.TwoPartyTradeFlow.Seller
|
||||
import net.corda.node.internal.StartedNode
|
||||
import net.corda.nodeapi.internal.ServiceInfo
|
||||
import net.corda.node.services.api.WritableTransactionStorage
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.persistence.DBTransactionStorage
|
||||
import net.corda.node.services.persistence.checkpoints
|
||||
import net.corda.node.utilities.CordaPersistence
|
||||
import net.corda.nodeapi.internal.ServiceInfo
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.contracts.fillWithSomeTestCash
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork
|
||||
@ -678,8 +681,8 @@ class TwoPartyTradeFlowTests {
|
||||
// wants to sell to Bob.
|
||||
val eb1 = transaction(transactionBuilder = TransactionBuilder(notary = notary)) {
|
||||
// Issued money to itself.
|
||||
output(CASH_PROGRAM_ID, "elbonian money 1", notary = notary) { 800.DOLLARS.CASH `issued by` issuer `owned by` interimOwner }
|
||||
output(CASH_PROGRAM_ID, "elbonian money 2", notary = notary) { 1000.DOLLARS.CASH `issued by` issuer `owned by` interimOwner }
|
||||
output(Cash.PROGRAM_ID, "elbonian money 1", notary = notary) { 800.DOLLARS.CASH `issued by` issuer `owned by` interimOwner }
|
||||
output(Cash.PROGRAM_ID, "elbonian money 2", notary = notary) { 1000.DOLLARS.CASH `issued by` issuer `owned by` interimOwner }
|
||||
if (!withError) {
|
||||
command(issuer.party.owningKey) { Cash.Commands.Issue() }
|
||||
} else {
|
||||
@ -697,15 +700,15 @@ class TwoPartyTradeFlowTests {
|
||||
// Bob gets some cash onto the ledger from BoE
|
||||
val bc1 = transaction(transactionBuilder = TransactionBuilder(notary = notary)) {
|
||||
input("elbonian money 1")
|
||||
output(CASH_PROGRAM_ID, "bob cash 1", notary = notary) { 800.DOLLARS.CASH `issued by` issuer `owned by` owner }
|
||||
output(Cash.PROGRAM_ID, "bob cash 1", notary = notary) { 800.DOLLARS.CASH `issued by` issuer `owned by` owner }
|
||||
command(interimOwner.owningKey) { Cash.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
val bc2 = transaction(transactionBuilder = TransactionBuilder(notary = notary)) {
|
||||
input("elbonian money 2")
|
||||
output(CASH_PROGRAM_ID, "bob cash 2", notary = notary) { 300.DOLLARS.CASH `issued by` issuer `owned by` owner }
|
||||
output(CASH_PROGRAM_ID, notary = notary) { 700.DOLLARS.CASH `issued by` issuer `owned by` interimOwner } // Change output.
|
||||
output(Cash.PROGRAM_ID, "bob cash 2", notary = notary) { 300.DOLLARS.CASH `issued by` issuer `owned by` owner }
|
||||
output(Cash.PROGRAM_ID, notary = notary) { 700.DOLLARS.CASH `issued by` issuer `owned by` interimOwner } // Change output.
|
||||
command(interimOwner.owningKey) { Cash.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
|
@ -14,9 +14,7 @@ import net.corda.node.internal.StartedNode
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.internal.ServiceInfo
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||
@ -145,9 +143,9 @@ class NotaryChangeTests {
|
||||
|
||||
val tx = TransactionBuilder(null).apply {
|
||||
addCommand(Command(DummyContract.Commands.Create(), owner.party.owningKey))
|
||||
addOutputState(stateA, DUMMY_PROGRAM_ID, notaryIdentity, encumbrance = 2) // Encumbered by stateB
|
||||
addOutputState(stateC, DUMMY_PROGRAM_ID, notaryIdentity)
|
||||
addOutputState(stateB, DUMMY_PROGRAM_ID, notaryIdentity, encumbrance = 1) // Encumbered by stateC
|
||||
addOutputState(stateA, DummyContract.PROGRAM_ID, notaryIdentity, encumbrance = 2) // Encumbered by stateB
|
||||
addOutputState(stateC, DummyContract.PROGRAM_ID, notaryIdentity)
|
||||
addOutputState(stateB, DummyContract.PROGRAM_ID, notaryIdentity, encumbrance = 1) // Encumbered by stateC
|
||||
}
|
||||
val stx = node.services.signInitialTransaction(tx)
|
||||
node.services.recordTransactions(stx)
|
||||
@ -173,7 +171,7 @@ fun issueState(node: StartedNode<*>, notaryNode: StartedNode<*>, notaryIdentity:
|
||||
|
||||
fun issueMultiPartyState(nodeA: StartedNode<*>, nodeB: StartedNode<*>, notaryNode: StartedNode<*>, notaryIdentity: Party): StateAndRef<DummyContract.MultiOwnerState> {
|
||||
val state = TransactionState(DummyContract.MultiOwnerState(0,
|
||||
listOf(nodeA.info.chooseIdentity(), nodeB.info.chooseIdentity())), DUMMY_PROGRAM_ID, notaryIdentity)
|
||||
listOf(nodeA.info.chooseIdentity(), nodeB.info.chooseIdentity())), DummyContract.PROGRAM_ID, notaryIdentity)
|
||||
val tx = TransactionBuilder(notary = notaryIdentity).withItems(state, dummyCommand())
|
||||
val signedByA = nodeA.services.signInitialTransaction(tx)
|
||||
val signedByAB = nodeB.services.addSignature(signedByA)
|
||||
|
@ -25,7 +25,7 @@ import net.corda.node.utilities.AffinityExecutor
|
||||
import net.corda.node.utilities.CordaPersistence
|
||||
import net.corda.node.utilities.configureDatabase
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork
|
||||
import net.corda.testing.node.MockKeyManagementService
|
||||
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||
@ -284,7 +284,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
|
||||
val freshKey = services.keyManagementService.freshKey()
|
||||
val state = TestState(FlowLogicRefFactoryImpl.createForRPC(TestFlowLogic::class.java, increment), instant, services.myInfo.chooseIdentity())
|
||||
val builder = TransactionBuilder(null).apply {
|
||||
addOutputState(state, DUMMY_PROGRAM_ID, DUMMY_NOTARY)
|
||||
addOutputState(state, DummyContract.PROGRAM_ID, DUMMY_NOTARY)
|
||||
addCommand(Command(), freshKey)
|
||||
}
|
||||
val usefulTX = services.signInitialTransaction(builder, freshKey)
|
||||
|
@ -20,9 +20,7 @@ import net.corda.node.services.statemachine.StateMachineManager
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.nodeapi.internal.ServiceInfo
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.dummyCommand
|
||||
import net.corda.testing.getDefaultNotary
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.junit.After
|
||||
import org.junit.Assert.*
|
||||
@ -65,7 +63,7 @@ class ScheduledFlowTests {
|
||||
val scheduledState = ScheduledState(serviceHub.clock.instant(), ourIdentity, destination)
|
||||
val notary = serviceHub.getDefaultNotary()
|
||||
val builder = TransactionBuilder(notary)
|
||||
.addOutputState(scheduledState, DUMMY_PROGRAM_ID)
|
||||
.addOutputState(scheduledState, DummyContract.PROGRAM_ID)
|
||||
.addCommand(dummyCommand(ourIdentity.owningKey))
|
||||
val tx = serviceHub.signInitialTransaction(builder)
|
||||
subFlow(FinalityFlow(tx))
|
||||
@ -87,7 +85,7 @@ class ScheduledFlowTests {
|
||||
val newStateOutput = scheduledState.copy(processed = true)
|
||||
val builder = TransactionBuilder(notary)
|
||||
.addInputState(state)
|
||||
.addOutputState(newStateOutput, DUMMY_PROGRAM_ID)
|
||||
.addOutputState(newStateOutput, DummyContract.PROGRAM_ID)
|
||||
.addCommand(dummyCommand(ourIdentity.owningKey))
|
||||
val tx = serviceHub.signInitialTransaction(builder)
|
||||
subFlow(FinalityFlow(tx, setOf(scheduledState.destination)))
|
||||
|
@ -1,6 +1,9 @@
|
||||
package net.corda.node.services.schema
|
||||
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.contracts.StateAndRef
|
||||
import net.corda.core.contracts.StateRef
|
||||
import net.corda.core.contracts.TransactionState
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.node.services.Vault
|
||||
@ -12,7 +15,7 @@ import net.corda.node.utilities.DatabaseTransactionManager
|
||||
import net.corda.node.utilities.configureDatabase
|
||||
import net.corda.testing.LogHelper
|
||||
import net.corda.testing.MEGA_CORP
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties
|
||||
import net.corda.testing.node.MockServices.Companion.makeTestIdentityService
|
||||
@ -72,7 +75,7 @@ class HibernateObserverTests {
|
||||
@Suppress("UNUSED_VARIABLE")
|
||||
val observer = HibernateObserver(rawUpdatesPublisher, database.hibernateConfig)
|
||||
database.transaction {
|
||||
rawUpdatesPublisher.onNext(Vault.Update(emptySet(), setOf(StateAndRef(TransactionState(TestState(), DUMMY_PROGRAM_ID, MEGA_CORP), StateRef(SecureHash.sha256("dummy"), 0)))))
|
||||
rawUpdatesPublisher.onNext(Vault.Update(emptySet(), setOf(StateAndRef(TransactionState(TestState(), DummyContract.PROGRAM_ID, MEGA_CORP), StateRef(SecureHash.sha256("dummy"), 0)))))
|
||||
val parentRowCountResult = DatabaseTransactionManager.current().connection.prepareStatement("select count(*) from Parents").executeQuery()
|
||||
parentRowCountResult.next()
|
||||
val parentRows = parentRowCountResult.getInt(1)
|
||||
|
@ -36,7 +36,7 @@ import net.corda.node.services.persistence.checkpoints
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
import net.corda.nodeapi.internal.ServiceInfo
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.contracts.DummyState
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork.MessageTransfer
|
||||
@ -608,7 +608,7 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `wait for transaction`() {
|
||||
val ptx = TransactionBuilder(notary = notary1Identity)
|
||||
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
|
||||
.addOutputState(DummyState(), DummyContract.PROGRAM_ID)
|
||||
.addCommand(dummyCommand(node1.info.chooseIdentity().owningKey))
|
||||
val stx = node1.services.signInitialTransaction(ptx)
|
||||
|
||||
@ -623,7 +623,7 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `committer throws exception before calling the finality flow`() {
|
||||
val ptx = TransactionBuilder(notary = notary1Identity)
|
||||
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
|
||||
.addOutputState(DummyState(), DummyContract.PROGRAM_ID)
|
||||
.addCommand(dummyCommand())
|
||||
val stx = node1.services.signInitialTransaction(ptx)
|
||||
|
||||
@ -640,7 +640,7 @@ class FlowFrameworkTests {
|
||||
@Test
|
||||
fun `verify vault query service is tokenizable by force checkpointing within a flow`() {
|
||||
val ptx = TransactionBuilder(notary = notary1Identity)
|
||||
.addOutputState(DummyState(), DUMMY_PROGRAM_ID)
|
||||
.addOutputState(DummyState(), DummyContract.PROGRAM_ID)
|
||||
.addCommand(dummyCommand(node1.info.chooseIdentity().owningKey))
|
||||
val stx = node1.services.signInitialTransaction(ptx)
|
||||
|
||||
|
@ -3,7 +3,6 @@ package net.corda.irs.api
|
||||
import net.corda.core.contracts.Command
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.contracts.TransactionState
|
||||
import net.corda.core.crypto.MerkleTreeException
|
||||
import net.corda.core.crypto.generateKeyPair
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
@ -13,7 +12,10 @@ import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.finance.DOLLARS
|
||||
import net.corda.finance.contracts.Fix
|
||||
import net.corda.finance.contracts.FixOf
|
||||
import net.corda.finance.contracts.asset.*
|
||||
import net.corda.finance.contracts.asset.CASH
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.contracts.asset.`issued by`
|
||||
import net.corda.finance.contracts.asset.`owned by`
|
||||
import net.corda.irs.flows.RatesFixFlow
|
||||
import net.corda.node.utilities.CordaPersistence
|
||||
import net.corda.node.utilities.configureDatabase
|
||||
@ -240,7 +242,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
|
||||
}
|
||||
|
||||
private fun makePartialTX() = TransactionBuilder(DUMMY_NOTARY).withItems(
|
||||
TransactionState(1000.DOLLARS.CASH `issued by` DUMMY_CASH_ISSUER `owned by` ALICE, CASH_PROGRAM_ID, DUMMY_NOTARY))
|
||||
TransactionState(1000.DOLLARS.CASH `issued by` DUMMY_CASH_ISSUER `owned by` ALICE, Cash.PROGRAM_ID, DUMMY_NOTARY))
|
||||
|
||||
private fun makeFullTx() = makePartialTX().withItems(dummyCommand())
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.contracts.DummyState
|
||||
import net.corda.testing.node.MockServices
|
||||
@ -36,7 +35,7 @@ class TransactionGraphSearchTests : TestDependencyInjectionBase() {
|
||||
val notaryServices = MockServices(listOf("net.corda.testing.contracts"), DUMMY_NOTARY_KEY)
|
||||
|
||||
val originBuilder = TransactionBuilder(DUMMY_NOTARY)
|
||||
.addOutputState(DummyState(random31BitValue()), DUMMY_PROGRAM_ID)
|
||||
.addOutputState(DummyState(random31BitValue()), DummyContract.PROGRAM_ID)
|
||||
.addCommand(command, MEGA_CORP_PUBKEY)
|
||||
|
||||
val originPtx = megaCorpServices.signInitialTransaction(originBuilder)
|
||||
|
@ -4,13 +4,11 @@ import net.corda.core.contracts.*
|
||||
import net.corda.core.cordapp.CordappProvider
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.crypto.NullKeys.NULL_SIGNATURE
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.node.MockCordappProvider
|
||||
import java.io.InputStream
|
||||
@ -258,7 +256,7 @@ data class TestLedgerDSLInterpreter private constructor(
|
||||
private fun fillTransaction(transactionBuilder: TransactionBuilder) {
|
||||
if (transactionBuilder.commands().isEmpty()) transactionBuilder.addCommand(dummyCommand())
|
||||
if (transactionBuilder.inputStates().isEmpty() && transactionBuilder.outputStates().isEmpty()) {
|
||||
transactionBuilder.addOutputState(DummyContract.SingleOwnerState(owner = ALICE), DUMMY_PROGRAM_ID)
|
||||
transactionBuilder.addOutputState(DummyContract.SingleOwnerState(owner = ALICE), DummyContract.PROGRAM_ID)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,8 +9,6 @@ import kotlin.reflect.jvm.jvmName
|
||||
|
||||
// The dummy contract doesn't do anything useful. It exists for testing purposes, but has to be serializable
|
||||
|
||||
const val DUMMY_PROGRAM_ID: ContractClassName = "net.corda.testing.contracts.DummyContract"
|
||||
|
||||
data class DummyContract(val blank: Any? = null) : Contract {
|
||||
interface State : ContractState {
|
||||
val magicNumber: Int
|
||||
@ -43,15 +41,17 @@ data class DummyContract(val blank: Any? = null) : Contract {
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PROGRAM_ID: ContractClassName = "net.corda.testing.contracts.DummyContract"
|
||||
|
||||
@JvmStatic
|
||||
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)
|
||||
TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), Command(Commands.Create(), owners.first().party.owningKey))
|
||||
TransactionBuilder(notary).withItems(StateAndContract(state, PROGRAM_ID), Command(Commands.Create(), owners.first().party.owningKey))
|
||||
} else {
|
||||
val state = MultiOwnerState(magicNumber, owners.map { it.party })
|
||||
TransactionBuilder(notary).withItems(StateAndContract(state, DUMMY_PROGRAM_ID), Command(Commands.Create(), owners.map { it.party.owningKey }))
|
||||
TransactionBuilder(notary).withItems(StateAndContract(state, PROGRAM_ID), Command(Commands.Create(), owners.map { it.party.owningKey }))
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ data class DummyContract(val blank: Any? = null) : Contract {
|
||||
return TransactionBuilder(notary = priors[0].state.notary).withItems(
|
||||
/* INPUTS */ *priors.toTypedArray(),
|
||||
/* COMMAND */ Command(cmd, priorState.owner.owningKey),
|
||||
/* OUTPUT */ StateAndContract(state, DUMMY_PROGRAM_ID)
|
||||
/* OUTPUT */ StateAndContract(state, PROGRAM_ID)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -9,13 +9,16 @@ import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
|
||||
// The dummy contract doesn't do anything useful. It exists for testing purposes.
|
||||
const val DUMMY_V2_PROGRAM_ID: ContractClassName = "net.corda.testing.contracts.DummyContractV2"
|
||||
|
||||
/**
|
||||
* Dummy contract state for testing of the upgrade process.
|
||||
*/
|
||||
// DOCSTART 1
|
||||
class DummyContractV2 : UpgradedContract<DummyContract.State, DummyContractV2.State> {
|
||||
companion object {
|
||||
const val PROGRAM_ID: ContractClassName = "net.corda.testing.contracts.DummyContractV2"
|
||||
}
|
||||
|
||||
override val legacyContract: String = DummyContract::class.java.name
|
||||
|
||||
data class State(val magicNumber: Int = 0, val owners: List<AbstractParty>) : ContractState {
|
||||
@ -52,8 +55,8 @@ class DummyContractV2 : UpgradedContract<DummyContract.State, DummyContractV2.St
|
||||
return Pair(TransactionBuilder(notary).apply {
|
||||
states.forEach {
|
||||
addInputState(it)
|
||||
addOutputState(upgrade(it.state.data), DUMMY_V2_PROGRAM_ID, it.state.constraint)
|
||||
addCommand(UpgradeCommand(DUMMY_V2_PROGRAM_ID), signees.map { it.owningKey }.toList())
|
||||
addOutputState(upgrade(it.state.data), DummyContractV2.PROGRAM_ID, it.state.constraint)
|
||||
addCommand(UpgradeCommand(DummyContractV2.PROGRAM_ID), signees.map { it.owningKey }.toList())
|
||||
}
|
||||
}.toWireTransaction(services), signees)
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import net.corda.core.identity.Party
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
import net.corda.core.transactions.WireTransaction
|
||||
import net.corda.nodeapi.internal.serialization.GeneratedAttachment
|
||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import java.math.BigInteger
|
||||
import java.security.PublicKey
|
||||
import java.util.*
|
||||
@ -37,7 +37,7 @@ data class GeneratedLedger(
|
||||
|
||||
companion object {
|
||||
val empty = GeneratedLedger(emptyList(), emptyMap(), emptySet(), emptySet())
|
||||
val contractAttachment = ContractAttachment(GeneratedAttachment(ByteArray(0) { 0 }), DUMMY_PROGRAM_ID)
|
||||
val contractAttachment = ContractAttachment(GeneratedAttachment(ByteArray(0) { 0 }), DummyContract.PROGRAM_ID)
|
||||
}
|
||||
|
||||
fun resolveWireTransaction(transaction: WireTransaction): LedgerTransaction {
|
||||
@ -69,7 +69,7 @@ data class GeneratedLedger(
|
||||
Generator.sequence(
|
||||
outputs.map { output ->
|
||||
pickOneOrMaybeNew(identities, partyGenerator).map { notary ->
|
||||
TransactionState(output, DUMMY_PROGRAM_ID, notary, null, HashAttachmentConstraint(contractAttachment.id))
|
||||
TransactionState(output, DummyContract.PROGRAM_ID, notary, null, HashAttachmentConstraint(contractAttachment.id))
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -134,7 +134,7 @@ data class GeneratedLedger(
|
||||
fun regularTransactionGenerator(inputNotary: Party, inputsToChooseFrom: List<StateAndRef<ContractState>>): Generator<Pair<WireTransaction, GeneratedLedger>> {
|
||||
val outputsGen = outputsGenerator.map { outputs ->
|
||||
outputs.map { output ->
|
||||
TransactionState(output, DUMMY_PROGRAM_ID, inputNotary, null, HashAttachmentConstraint(contractAttachment.id))
|
||||
TransactionState(output, DummyContract.PROGRAM_ID, inputNotary, null, HashAttachmentConstraint(contractAttachment.id))
|
||||
}
|
||||
}
|
||||
val inputsGen = Generator.sampleBernoulli(inputsToChooseFrom)
|
||||
|
Loading…
Reference in New Issue
Block a user