mirror of
https://github.com/corda/corda.git
synced 2024-12-20 05:28:21 +00:00
Remove type-specific transaction builder. Normal transactions should use TransactionBuilder and notary change transactions are created directly.
This commit is contained in:
parent
59edd6f9ae
commit
4ca8b8d681
@ -80,7 +80,7 @@ interface ContractState {
|
|||||||
* A _participant_ is any party that is able to consume this state in a valid transaction.
|
* A _participant_ is any party that is able to consume this state in a valid transaction.
|
||||||
*
|
*
|
||||||
* The list of participants is required for certain types of transactions. For example, when changing the notary
|
* The list of participants is required for certain types of transactions. For example, when changing the notary
|
||||||
* for this state ([TransactionType.NotaryChange]), every participant has to be involved and approve the transaction
|
* for this state, every participant has to be involved and approve the transaction
|
||||||
* so that they receive the updated state, and don't end up in a situation where they can no longer use a state
|
* so that they receive the updated state, and don't end up in a situation where they can no longer use a state
|
||||||
* they possess, since someone consumed that state during the notary change process.
|
* they possess, since someone consumed that state during the notary change process.
|
||||||
*
|
*
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
package net.corda.core.contracts
|
|
||||||
|
|
||||||
import net.corda.core.identity.Party
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
|
||||||
|
|
||||||
/** Defines transaction build & validation logic for a specific transaction type */
|
|
||||||
@CordaSerializable
|
|
||||||
// TODO: remove this concept
|
|
||||||
sealed class TransactionType {
|
|
||||||
/** A general transaction type where transaction validity is determined by custom contract code */
|
|
||||||
object General : TransactionType() {
|
|
||||||
/** Just uses the default [TransactionBuilder] with no special logic */
|
|
||||||
@Deprecated("Use TransactionBuilder directly instead", ReplaceWith("TransactionBuilder()"))
|
|
||||||
class Builder(notary: Party?) : TransactionBuilder(notary)
|
|
||||||
}
|
|
||||||
}
|
|
@ -42,7 +42,7 @@ import java.security.PublicKey
|
|||||||
*
|
*
|
||||||
* Example - issuing a multi-lateral agreement which requires N signatures:
|
* Example - issuing a multi-lateral agreement which requires N signatures:
|
||||||
*
|
*
|
||||||
* val builder = TransactionType.General.Builder(notaryRef)
|
* val builder = TransactionBuilder(notaryRef)
|
||||||
* val issueCommand = Command(Agreement.Commands.Issue(), state.participants)
|
* val issueCommand = Command(Agreement.Commands.Issue(), state.participants)
|
||||||
*
|
*
|
||||||
* builder.withItems(state, issueCommand)
|
* builder.withItems(state, issueCommand)
|
||||||
|
@ -51,7 +51,7 @@ class ContractUpgradeFlow<OldState : ContractState, out NewState : ContractState
|
|||||||
privacySalt: PrivacySalt
|
privacySalt: PrivacySalt
|
||||||
): TransactionBuilder {
|
): TransactionBuilder {
|
||||||
val contractUpgrade = upgradedContractClass.newInstance()
|
val contractUpgrade = upgradedContractClass.newInstance()
|
||||||
return TransactionType.General.Builder(stateRef.state.notary)
|
return TransactionBuilder(stateRef.state.notary)
|
||||||
.withItems(
|
.withItems(
|
||||||
stateRef,
|
stateRef,
|
||||||
contractUpgrade.upgrade(stateRef.state.data),
|
contractUpgrade.upgrade(stateRef.state.data),
|
||||||
|
Binary file not shown.
@ -2,6 +2,7 @@ package net.corda.core.contracts
|
|||||||
|
|
||||||
import net.corda.core.crypto.newSecureRandom
|
import net.corda.core.crypto.newSecureRandom
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.transactions.WireTransaction
|
import net.corda.core.transactions.WireTransaction
|
||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
@ -32,14 +33,14 @@ class TransactionGraphSearchTests : TestDependencyInjectionBase() {
|
|||||||
val megaCorpServices = MockServices(MEGA_CORP_KEY)
|
val megaCorpServices = MockServices(MEGA_CORP_KEY)
|
||||||
val notaryServices = MockServices(DUMMY_NOTARY_KEY)
|
val notaryServices = MockServices(DUMMY_NOTARY_KEY)
|
||||||
|
|
||||||
val originBuilder = TransactionType.General.Builder(DUMMY_NOTARY)
|
val originBuilder = TransactionBuilder(DUMMY_NOTARY)
|
||||||
originBuilder.addOutputState(DummyState(random31BitValue()))
|
originBuilder.addOutputState(DummyState(random31BitValue()))
|
||||||
originBuilder.addCommand(command, MEGA_CORP_PUBKEY)
|
originBuilder.addCommand(command, MEGA_CORP_PUBKEY)
|
||||||
|
|
||||||
val originPtx = megaCorpServices.signInitialTransaction(originBuilder)
|
val originPtx = megaCorpServices.signInitialTransaction(originBuilder)
|
||||||
val originTx = notaryServices.addSignature(originPtx)
|
val originTx = notaryServices.addSignature(originPtx)
|
||||||
|
|
||||||
val inputBuilder = TransactionType.General.Builder(DUMMY_NOTARY)
|
val inputBuilder = TransactionBuilder(DUMMY_NOTARY)
|
||||||
inputBuilder.addInputState(originTx.tx.outRef<DummyState>(0))
|
inputBuilder.addInputState(originTx.tx.outRef<DummyState>(0))
|
||||||
|
|
||||||
val inputPtx = megaCorpServices.signInitialTransaction(inputBuilder)
|
val inputPtx = megaCorpServices.signInitialTransaction(inputBuilder)
|
||||||
|
@ -2,11 +2,11 @@ package net.corda.core.flows
|
|||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.core.contracts.Command
|
import net.corda.core.contracts.Command
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.contracts.requireThat
|
import net.corda.core.contracts.requireThat
|
||||||
import net.corda.core.getOrThrow
|
import net.corda.core.getOrThrow
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.unwrap
|
import net.corda.core.utilities.unwrap
|
||||||
import net.corda.testing.MINI_CORP_KEY
|
import net.corda.testing.MINI_CORP_KEY
|
||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
@ -84,7 +84,7 @@ class CollectSignaturesFlowTests {
|
|||||||
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
|
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
|
||||||
|
|
||||||
val command = Command(DummyContract.Commands.Create(), state.participants.map { it.owningKey })
|
val command = Command(DummyContract.Commands.Create(), state.participants.map { it.owningKey })
|
||||||
val builder = TransactionType.General.Builder(notary = notary).withItems(state, command)
|
val builder = TransactionBuilder(notary).withItems(state, command)
|
||||||
val ptx = serviceHub.signInitialTransaction(builder)
|
val ptx = serviceHub.signInitialTransaction(builder)
|
||||||
val stx = subFlow(CollectSignaturesFlow(ptx))
|
val stx = subFlow(CollectSignaturesFlow(ptx))
|
||||||
val ftx = subFlow(FinalityFlow(stx)).single()
|
val ftx = subFlow(FinalityFlow(stx)).single()
|
||||||
@ -104,7 +104,7 @@ class CollectSignaturesFlowTests {
|
|||||||
override fun call(): SignedTransaction {
|
override fun call(): SignedTransaction {
|
||||||
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
|
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
|
||||||
val command = Command(DummyContract.Commands.Create(), state.participants.map { it.owningKey })
|
val command = Command(DummyContract.Commands.Create(), state.participants.map { it.owningKey })
|
||||||
val builder = TransactionType.General.Builder(notary = notary).withItems(state, command)
|
val builder = TransactionBuilder(notary).withItems(state, command)
|
||||||
val ptx = serviceHub.signInitialTransaction(builder)
|
val ptx = serviceHub.signInitialTransaction(builder)
|
||||||
val stx = subFlow(CollectSignaturesFlow(ptx))
|
val stx = subFlow(CollectSignaturesFlow(ptx))
|
||||||
val ftx = subFlow(FinalityFlow(stx)).single()
|
val ftx = subFlow(FinalityFlow(stx)).single()
|
||||||
|
@ -4,7 +4,6 @@ import net.corda.contracts.asset.Cash
|
|||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
import net.corda.core.contracts.GBP
|
import net.corda.core.contracts.GBP
|
||||||
import net.corda.core.contracts.Issued
|
import net.corda.core.contracts.Issued
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.getOrThrow
|
import net.corda.core.getOrThrow
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
|
@ -67,7 +67,7 @@ class AttachmentClassLoaderTests : TestDependencyInjectionBase() {
|
|||||||
|
|
||||||
fun generateInitial(owner: PartyAndReference, magicNumber: Int, notary: Party): TransactionBuilder {
|
fun generateInitial(owner: PartyAndReference, magicNumber: Int, notary: Party): TransactionBuilder {
|
||||||
val state = State(magicNumber)
|
val state = State(magicNumber)
|
||||||
return TransactionType.General.Builder(notary = notary).withItems(state, Command(Commands.Create(), owner.party.owningKey))
|
return TransactionBuilder(notary).withItems(state, Command(Commands.Create(), owner.party.owningKey))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class TransactionSerializationTests : TestDependencyInjectionBase() {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
tx = TransactionType.General.Builder(DUMMY_NOTARY).withItems(
|
tx = TransactionBuilder(DUMMY_NOTARY).withItems(
|
||||||
inputState, outputState, changeState, Command(TestCash.Commands.Move(), arrayListOf(MEGA_CORP.owningKey))
|
inputState, outputState, changeState, Command(TestCash.Commands.Move(), arrayListOf(MEGA_CORP.owningKey))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ class TransactionSerializationTests : TestDependencyInjectionBase() {
|
|||||||
|
|
||||||
// If the signature was replaced in transit, we don't like it.
|
// If the signature was replaced in transit, we don't like it.
|
||||||
assertFailsWith(SignatureException::class) {
|
assertFailsWith(SignatureException::class) {
|
||||||
val tx2 = TransactionType.General.Builder(DUMMY_NOTARY).withItems(inputState, outputState, changeState,
|
val tx2 = TransactionBuilder(DUMMY_NOTARY).withItems(inputState, outputState, changeState,
|
||||||
Command(TestCash.Commands.Move(), DUMMY_KEY_2.public))
|
Command(TestCash.Commands.Move(), DUMMY_KEY_2.public))
|
||||||
|
|
||||||
val ptx2 = notaryServices.signInitialTransaction(tx2)
|
val ptx2 = notaryServices.signInitialTransaction(tx2)
|
||||||
|
@ -96,7 +96,6 @@ Where:
|
|||||||
* ``id`` is the transaction's merkle root hash'
|
* ``id`` is the transaction's merkle root hash'
|
||||||
* ``notary`` is the transaction's notary. If there are inputs these must have the same notary on their source transactions.
|
* ``notary`` is the transaction's notary. If there are inputs these must have the same notary on their source transactions.
|
||||||
* ``timeWindow`` is the transaction's timestamp and defines the acceptable delay for notarisation.
|
* ``timeWindow`` is the transaction's timestamp and defines the acceptable delay for notarisation.
|
||||||
* ``type`` is the class of Transaction. Normal ledger data transactions are ``TransactionType.General``, but migration of states to a new notary uses ``TransactionType.NotaryChange``.
|
|
||||||
|
|
||||||
requireThat()
|
requireThat()
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
|
@ -9,36 +9,6 @@ API: Transactions
|
|||||||
|
|
||||||
.. note:: Before reading this page, you should be familiar with the key concepts of :doc:`key-concepts-transactions`.
|
.. note:: Before reading this page, you should be familiar with the key concepts of :doc:`key-concepts-transactions`.
|
||||||
|
|
||||||
Transaction types
|
|
||||||
-----------------
|
|
||||||
There are two types of transaction in Corda:
|
|
||||||
|
|
||||||
* ``TransactionType.NotaryChange``, used to change the notary for a set of states
|
|
||||||
* ``TransactionType.General``, for transactions other than notary-change transactions
|
|
||||||
|
|
||||||
Notary-change transactions
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
A single Corda network will usually have multiple notary services. To commit a transaction, we require a signature
|
|
||||||
from the notary service associated with each input state. If we tried to commit a transaction where the input
|
|
||||||
states were associated with different notary services, the transaction would require a signature from multiple notary
|
|
||||||
services, creating a complicated multi-phase commit scenario. To prevent this, every input state in a transaction
|
|
||||||
must be associated the same notary.
|
|
||||||
|
|
||||||
However, we will often need to create a transaction involving input states associated with different notaries. Before
|
|
||||||
we can create this transaction, we will need to change the notary service associated with each state by:
|
|
||||||
|
|
||||||
* Deciding which notary service we want to notarise the transaction
|
|
||||||
* For each set of inputs states that point to the same notary service that isn't the desired notary service, creating a
|
|
||||||
``TransactionType.NotaryChange`` transaction that:
|
|
||||||
|
|
||||||
* Consumes the input states pointing to the old notary
|
|
||||||
* Outputs the same states, but that now point to the new notary
|
|
||||||
|
|
||||||
* Using the outputs of the notary-change transactions as inputs to a standard ``TransactionType.General`` transaction
|
|
||||||
|
|
||||||
In practice, this process is handled automatically by a built-in flow called ``NotaryChangeFlow``. See
|
|
||||||
:doc:`api-flows` for more details.
|
|
||||||
|
|
||||||
Transaction workflow
|
Transaction workflow
|
||||||
--------------------
|
--------------------
|
||||||
There are four states the transaction can occupy:
|
There are four states the transaction can occupy:
|
||||||
@ -590,3 +560,22 @@ Notarising and recording
|
|||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
Notarising and recording a transaction is handled by a built-in flow called ``FinalityFlow``. See
|
Notarising and recording a transaction is handled by a built-in flow called ``FinalityFlow``. See
|
||||||
:doc:`api-flows` for more details.
|
:doc:`api-flows` for more details.
|
||||||
|
|
||||||
|
Notary-change transactions
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
A single Corda network will usually have multiple notary services. To commit a transaction, we require a signature
|
||||||
|
from the notary service associated with each input state. If we tried to commit a transaction where the input
|
||||||
|
states were associated with different notary services, the transaction would require a signature from multiple notary
|
||||||
|
services, creating a complicated multi-phase commit scenario. To prevent this, every input state in a transaction
|
||||||
|
must be associated with the same notary.
|
||||||
|
|
||||||
|
However, we will often need to create a transaction involving input states associated with different notaries. Before
|
||||||
|
we can create this transaction, we will need to change the notary service associated with each state by:
|
||||||
|
|
||||||
|
* Deciding which notary service we want to notarise the transaction
|
||||||
|
* Creating a special ``NotaryChangeWireTransaction`` that consumes the input states pointing to the old notary and
|
||||||
|
produces outputs which are identical but point to the new notary service
|
||||||
|
* Using the outputs of the notary-change transactions as inputs to a standard transaction
|
||||||
|
|
||||||
|
In practice, this process is handled automatically by a built-in flow called ``NotaryChangeFlow``. See
|
||||||
|
:doc:`api-flows` for more details.
|
@ -7,6 +7,9 @@ from the previous milestone release.
|
|||||||
UNRELEASED
|
UNRELEASED
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
* The concept of ``TransactionType`` has been removed. Transactions no longer carry a `type` property. All usages of
|
||||||
|
``TransactionType.General.Builder()`` have to be replaced with ``TransactionBuilder()``.
|
||||||
|
|
||||||
* Changes in ``NodeInfo``:
|
* Changes in ``NodeInfo``:
|
||||||
|
|
||||||
* ``PhysicalLocation`` was renamed to ``WorldMapLocation`` to emphasise that it doesn't need to map to a truly physical
|
* ``PhysicalLocation`` was renamed to ``WorldMapLocation`` to emphasise that it doesn't need to map to a truly physical
|
||||||
|
@ -5,7 +5,6 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import net.corda.contracts.asset.Cash;
|
import net.corda.contracts.asset.Cash;
|
||||||
import net.corda.core.contracts.*;
|
import net.corda.core.contracts.*;
|
||||||
import net.corda.core.contracts.TransactionType.General;
|
|
||||||
import net.corda.core.crypto.DigitalSignature;
|
import net.corda.core.crypto.DigitalSignature;
|
||||||
import net.corda.core.crypto.SecureHash;
|
import net.corda.core.crypto.SecureHash;
|
||||||
import net.corda.core.flows.*;
|
import net.corda.core.flows.*;
|
||||||
|
@ -3,7 +3,6 @@ package net.corda.docs
|
|||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.contracts.asset.Cash
|
import net.corda.contracts.asset.Cash
|
||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.contracts.TransactionType.General
|
|
||||||
import net.corda.core.crypto.DigitalSignature
|
import net.corda.core.crypto.DigitalSignature
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
|
@ -5,7 +5,6 @@ import net.corda.contracts.asset.Cash
|
|||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
import net.corda.core.contracts.Issued
|
import net.corda.core.contracts.Issued
|
||||||
import net.corda.core.contracts.StateAndRef
|
import net.corda.core.contracts.StateAndRef
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.crypto.DigitalSignature
|
import net.corda.core.crypto.DigitalSignature
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
@ -16,6 +15,7 @@ import net.corda.core.node.services.queryBy
|
|||||||
import net.corda.core.node.services.vault.QueryCriteria
|
import net.corda.core.node.services.vault.QueryCriteria
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.unwrap
|
import net.corda.core.utilities.unwrap
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ class ForeignExchangeFlow(val tradeId: String,
|
|||||||
// This is the correct way to create a TransactionBuilder,
|
// This is the correct way to create a TransactionBuilder,
|
||||||
// do not construct directly.
|
// do not construct directly.
|
||||||
// We also set the notary to match the input notary
|
// We also set the notary to match the input notary
|
||||||
val builder = TransactionType.General.Builder(ourStates.inputs.first().state.notary)
|
val builder = TransactionBuilder(ourStates.inputs.first().state.notary)
|
||||||
|
|
||||||
// Add the move commands and key to indicate all the respective owners and need to sign
|
// Add the move commands and key to indicate all the respective owners and need to sign
|
||||||
val ourSigners = ourStates.inputs.map { it.state.data.owner.owningKey }.toSet()
|
val ourSigners = ourStates.inputs.map { it.state.data.owner.owningKey }.toSet()
|
||||||
|
@ -16,6 +16,7 @@ import net.corda.core.node.services.linearHeadsOfType
|
|||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.transactions.LedgerTransaction
|
import net.corda.core.transactions.LedgerTransaction
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.core.utilities.unwrap
|
import net.corda.core.utilities.unwrap
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
@ -122,7 +123,7 @@ class SubmitTradeApprovalFlow(val tradeId: String,
|
|||||||
// identify a notary. This might also be done external to the flow
|
// identify a notary. This might also be done external to the flow
|
||||||
val notary = serviceHub.networkMapCache.getAnyNotary()
|
val notary = serviceHub.networkMapCache.getAnyNotary()
|
||||||
// Create the TransactionBuilder and populate with the new state.
|
// Create the TransactionBuilder and populate with the new state.
|
||||||
val tx = TransactionType.General.Builder(notary)
|
val tx = TransactionBuilder(notary)
|
||||||
.withItems(tradeProposal, Command(TradeApprovalContract.Commands.Issue(), listOf(tradeProposal.source.owningKey)))
|
.withItems(tradeProposal, Command(TradeApprovalContract.Commands.Issue(), listOf(tradeProposal.source.owningKey)))
|
||||||
tx.setTimeWindow(serviceHub.clock.instant(), 60.seconds)
|
tx.setTimeWindow(serviceHub.clock.instant(), 60.seconds)
|
||||||
// We can automatically sign as there is no untrusted data.
|
// We can automatically sign as there is no untrusted data.
|
||||||
@ -177,9 +178,7 @@ class SubmitCompletionFlow(val ref: StateRef, val verdict: WorkflowState) : Flow
|
|||||||
// To destroy the old proposal state and replace with the new completion state.
|
// To destroy the old proposal state and replace with the new completion state.
|
||||||
// Also add the Completed command with keys of all parties to signal the Tx purpose
|
// Also add the Completed command with keys of all parties to signal the Tx purpose
|
||||||
// to the Contract verify method.
|
// to the Contract verify method.
|
||||||
val tx = TransactionType.
|
val tx = TransactionBuilder(notary).
|
||||||
General.
|
|
||||||
Builder(notary).
|
|
||||||
withItems(
|
withItems(
|
||||||
latestRecord,
|
latestRecord,
|
||||||
newState,
|
newState,
|
||||||
|
@ -104,7 +104,7 @@ transaction and send it to the recipient node:
|
|||||||
|
|
||||||
// Create a trivial transaction that just passes across the attachment - in normal cases there would be
|
// Create a trivial transaction that just passes across the attachment - in normal cases there would be
|
||||||
// inputs, outputs and commands that refer to this attachment.
|
// inputs, outputs and commands that refer to this attachment.
|
||||||
val ptx = TransactionType.General.Builder(notary = null)
|
val ptx = TransactionBuilder(notary = null)
|
||||||
require(rpc.attachmentExists(PROSPECTUS_HASH))
|
require(rpc.attachmentExists(PROSPECTUS_HASH))
|
||||||
ptx.addAttachment(PROSPECTUS_HASH)
|
ptx.addAttachment(PROSPECTUS_HASH)
|
||||||
// TODO: Add a dummy state and specify a notary, so that the tx hash is randomised each time and the demo can be repeated.
|
// TODO: Add a dummy state and specify a notary, so that the tx hash is randomised each time and the demo can be repeated.
|
||||||
|
@ -4,102 +4,102 @@ Building transactions
|
|||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Understanding and implementing transactions in Corda is key to building
|
Understanding and implementing transactions in Corda is key to building
|
||||||
and implementing real world smart contracts. It is only through
|
and implementing real world smart contracts. It is only through
|
||||||
construction of valid Corda transactions containing appropriate data
|
construction of valid Corda transactions containing appropriate data
|
||||||
that nodes on the ledger can map real world business objects into a
|
that nodes on the ledger can map real world business objects into a
|
||||||
shared digital view of the data in the Corda ledger. More importantly as
|
shared digital view of the data in the Corda ledger. More importantly as
|
||||||
the developer of new smart contracts it is the code which determines
|
the developer of new smart contracts it is the code which determines
|
||||||
what data is well formed and what data should be rejected as mistakes,
|
what data is well formed and what data should be rejected as mistakes,
|
||||||
or to prevent malicious activity. This document details some of the
|
or to prevent malicious activity. This document details some of the
|
||||||
considerations and APIs used to when constructing transactions as part
|
considerations and APIs used to when constructing transactions as part
|
||||||
of a flow.
|
of a flow.
|
||||||
|
|
||||||
The Basic Lifecycle Of Transactions
|
The Basic Lifecycle Of Transactions
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
Transactions in Corda are constructed in stages and contain a number of
|
Transactions in Corda are constructed in stages and contain a number of
|
||||||
elements. In particular a transaction’s core data structure is the
|
elements. In particular a transaction’s core data structure is the
|
||||||
``net.corda.core.transactions.WireTransaction``, which is usually
|
``net.corda.core.transactions.WireTransaction``, which is usually
|
||||||
manipulated via a
|
manipulated via a
|
||||||
``net.corda.core.contracts.General.TransactionBuilder`` and contains:
|
``net.corda.core.transactions.TransactionBuilder`` and contains:
|
||||||
|
|
||||||
1. A set of Input state references that will be consumed by the final
|
1. A set of Input state references that will be consumed by the final
|
||||||
accepted transaction.
|
accepted transaction.
|
||||||
|
|
||||||
2. A set of Output states to create/replace the consumed states and thus
|
2. A set of Output states to create/replace the consumed states and thus
|
||||||
become the new latest versions of data on the ledger.
|
become the new latest versions of data on the ledger.
|
||||||
|
|
||||||
3. A set of ``Attachment`` items which can contain legal documents, contract
|
3. A set of ``Attachment`` items which can contain legal documents, contract
|
||||||
code, or private encrypted sections as an extension beyond the native
|
code, or private encrypted sections as an extension beyond the native
|
||||||
contract states.
|
contract states.
|
||||||
|
|
||||||
4. A set of ``Command`` items which give a context to the type of ledger
|
4. A set of ``Command`` items which give a context to the type of ledger
|
||||||
transition that is encoded in the transaction. Also each command has an
|
transition that is encoded in the transaction. Also each command has an
|
||||||
associated set of signer keys, which will be required to sign the
|
associated set of signer keys, which will be required to sign the
|
||||||
transaction.
|
transaction.
|
||||||
|
|
||||||
5. A signers list, which is populated by the ``TransactionBuilder`` to
|
5. A signers list, which is populated by the ``TransactionBuilder`` to
|
||||||
be the union of the signers on the individual Command objects.
|
be the union of the signers on the individual Command objects.
|
||||||
|
|
||||||
6. A notary identity to specify the Notary node which is tracking the
|
6. A notary identity to specify the Notary node which is tracking the
|
||||||
state consumption. (If the input states are registered with different
|
state consumption. (If the input states are registered with different
|
||||||
notary nodes the flow will have to insert additional ``NotaryChange``
|
notary nodes the flow will have to insert additional ``NotaryChange``
|
||||||
transactions to migrate the states across to a consistent notary node,
|
transactions to migrate the states across to a consistent notary node,
|
||||||
before being allowed to mutate any states.)
|
before being allowed to mutate any states.)
|
||||||
|
|
||||||
7. Optionally a timestamp that can used in the Notary to time bound the
|
7. Optionally a timestamp that can used in the Notary to time bound the
|
||||||
period in which the proposed transaction stays valid.
|
period in which the proposed transaction stays valid.
|
||||||
|
|
||||||
Typically, the ``WireTransaction`` should be regarded as a proposal and
|
Typically, the ``WireTransaction`` should be regarded as a proposal and
|
||||||
may need to be exchanged back and forth between parties before it can be
|
may need to be exchanged back and forth between parties before it can be
|
||||||
fully populated. This is an immediate consequence of the Corda privacy
|
fully populated. This is an immediate consequence of the Corda privacy
|
||||||
model, which means that the input states are likely to be unknown to the
|
model, which means that the input states are likely to be unknown to the
|
||||||
other node.
|
other node.
|
||||||
|
|
||||||
Once the proposed data is fully populated the flow code should freeze
|
Once the proposed data is fully populated the flow code should freeze
|
||||||
the ``WireTransaction`` and form a ``SignedTransaction``. This is key to
|
the ``WireTransaction`` and form a ``SignedTransaction``. This is key to
|
||||||
the ledger agreement process, as once a flow has attached a node’s
|
the ledger agreement process, as once a flow has attached a node’s
|
||||||
signature it has stated that all details of the transaction are
|
signature it has stated that all details of the transaction are
|
||||||
acceptable to it. A flow should take care not to attach signatures to
|
acceptable to it. A flow should take care not to attach signatures to
|
||||||
intermediate data, which might be maliciously used to construct a
|
intermediate data, which might be maliciously used to construct a
|
||||||
different ``SignedTransaction``. For instance in a foreign exchange
|
different ``SignedTransaction``. For instance in a foreign exchange
|
||||||
scenario we shouldn't send a ``SignedTransaction`` with only our sell
|
scenario we shouldn't send a ``SignedTransaction`` with only our sell
|
||||||
side populated as that could be used to take the money without the
|
side populated as that could be used to take the money without the
|
||||||
expected return of the other currency. Also, it is best practice for
|
expected return of the other currency. Also, it is best practice for
|
||||||
flows to receive back the ``DigitalSignature.WithKey`` of other parties
|
flows to receive back the ``DigitalSignature.WithKey`` of other parties
|
||||||
rather than a full ``SignedTransaction`` objects, because otherwise we
|
rather than a full ``SignedTransaction`` objects, because otherwise we
|
||||||
have to separately check that this is still the same
|
have to separately check that this is still the same
|
||||||
``SignedTransaction`` and not a malicious substitute.
|
``SignedTransaction`` and not a malicious substitute.
|
||||||
|
|
||||||
The final stage of committing the transaction to the ledger is to
|
The final stage of committing the transaction to the ledger is to
|
||||||
notarise the ``SignedTransaction``, distribute this to all appropriate
|
notarise the ``SignedTransaction``, distribute this to all appropriate
|
||||||
parties and record the data into the ledger. These actions are best
|
parties and record the data into the ledger. These actions are best
|
||||||
delegated to the ``FinalityFlow``, rather than calling the individual
|
delegated to the ``FinalityFlow``, rather than calling the individual
|
||||||
steps manually. However, do note that the final broadcast to the other
|
steps manually. However, do note that the final broadcast to the other
|
||||||
nodes is asynchronous, so care must be used in unit testing to
|
nodes is asynchronous, so care must be used in unit testing to
|
||||||
correctly await the Vault updates.
|
correctly await the Vault updates.
|
||||||
|
|
||||||
Gathering Inputs
|
Gathering Inputs
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
One of the first steps to forming a transaction is gathering the set of
|
One of the first steps to forming a transaction is gathering the set of
|
||||||
input references. This process will clearly vary according to the nature
|
input references. This process will clearly vary according to the nature
|
||||||
of the business process being captured by the smart contract and the
|
of the business process being captured by the smart contract and the
|
||||||
parameterised details of the request. However, it will generally involve
|
parameterised details of the request. However, it will generally involve
|
||||||
searching the Vault via the ``VaultService`` interface on the
|
searching the Vault via the ``VaultService`` interface on the
|
||||||
``ServiceHub`` to locate the input states.
|
``ServiceHub`` to locate the input states.
|
||||||
|
|
||||||
To give a few more specific details consider two simplified real world
|
To give a few more specific details consider two simplified real world
|
||||||
scenarios. First, a basic foreign exchange Cash transaction. This
|
scenarios. First, a basic foreign exchange Cash transaction. This
|
||||||
transaction needs to locate a set of funds to exchange. A flow
|
transaction needs to locate a set of funds to exchange. A flow
|
||||||
modelling this is implemented in ``FxTransactionBuildTutorial.kt``.
|
modelling this is implemented in ``FxTransactionBuildTutorial.kt``.
|
||||||
Second, a simple business model in which parties manually accept, or
|
Second, a simple business model in which parties manually accept, or
|
||||||
reject each other's trade proposals which is implemented in
|
reject each other's trade proposals which is implemented in
|
||||||
``WorkflowTransactionBuildTutorial.kt``. To run and explore these
|
``WorkflowTransactionBuildTutorial.kt``. To run and explore these
|
||||||
examples using the IntelliJ IDE one can run/step the respective unit
|
examples using the IntelliJ IDE one can run/step the respective unit
|
||||||
tests in ``FxTransactionBuildTutorialTest.kt`` and
|
tests in ``FxTransactionBuildTutorialTest.kt`` and
|
||||||
``WorkflowTransactionBuildTutorialTest.kt``, which drive the flows as
|
``WorkflowTransactionBuildTutorialTest.kt``, which drive the flows as
|
||||||
part of a simulated in-memory network of nodes.
|
part of a simulated in-memory network of nodes.
|
||||||
|
|
||||||
.. |nbsp| unicode:: 0xA0
|
.. |nbsp| unicode:: 0xA0
|
||||||
@ -111,53 +111,53 @@ part of a simulated in-memory network of nodes.
|
|||||||
to the VM options, and set Working directory to ``$PROJECT_DIR$``
|
to the VM options, and set Working directory to ``$PROJECT_DIR$``
|
||||||
so that the ``Quasar`` instrumentation is correctly configured.
|
so that the ``Quasar`` instrumentation is correctly configured.
|
||||||
|
|
||||||
For the Cash transaction let’s assume the cash resources are using the
|
For the Cash transaction let’s assume the cash resources are using the
|
||||||
standard ``CashState`` in the ``:financial`` Gradle module. The Cash
|
standard ``CashState`` in the ``:financial`` Gradle module. The Cash
|
||||||
contract uses ``FungibleAsset`` states to model holdings of
|
contract uses ``FungibleAsset`` states to model holdings of
|
||||||
interchangeable assets and allow the split/merge and summing of
|
interchangeable assets and allow the split/merge and summing of
|
||||||
states to meet a contractual obligation. We would normally use the
|
states to meet a contractual obligation. We would normally use the
|
||||||
``generateSpend`` method on the ``VaultService`` to gather the required
|
``generateSpend`` method on the ``VaultService`` to gather the required
|
||||||
amount of cash into a ``TransactionBuilder``, set the outputs and move
|
amount of cash into a ``TransactionBuilder``, set the outputs and move
|
||||||
command. However, to elucidate more clearly example flow code is shown
|
command. However, to elucidate more clearly example flow code is shown
|
||||||
here that will manually carry out the inputs queries using the lower
|
here that will manually carry out the inputs queries using the lower
|
||||||
level ``VaultService``.
|
level ``VaultService``.
|
||||||
|
|
||||||
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt
|
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt
|
||||||
:language: kotlin
|
:language: kotlin
|
||||||
:start-after: DOCSTART 1
|
:start-after: DOCSTART 1
|
||||||
:end-before: DOCEND 1
|
:end-before: DOCEND 1
|
||||||
|
|
||||||
As a foreign exchange transaction we expect an exchange of two
|
As a foreign exchange transaction we expect an exchange of two
|
||||||
currencies, so we will also require a set of input states from the other
|
currencies, so we will also require a set of input states from the other
|
||||||
counterparty. However, the Corda privacy model means we do not know the
|
counterparty. However, the Corda privacy model means we do not know the
|
||||||
other node’s states. Our flow must therefore negotiate with the other
|
other node’s states. Our flow must therefore negotiate with the other
|
||||||
node for them to carry out a similar query and populate the inputs (See
|
node for them to carry out a similar query and populate the inputs (See
|
||||||
the ``ForeignExchangeFlow`` for more details of the exchange). Having
|
the ``ForeignExchangeFlow`` for more details of the exchange). Having
|
||||||
identified a set of Input ``StateRef`` items we can then create the
|
identified a set of Input ``StateRef`` items we can then create the
|
||||||
output as discussed below.
|
output as discussed below.
|
||||||
|
|
||||||
For the trade approval flow we need to implement a simple workflow
|
For the trade approval flow we need to implement a simple workflow
|
||||||
pattern. We start by recording the unconfirmed trade details in a state
|
pattern. We start by recording the unconfirmed trade details in a state
|
||||||
object implementing the ``LinearState`` interface. One field of this
|
object implementing the ``LinearState`` interface. One field of this
|
||||||
record is used to map the business workflow to an enumerated state.
|
record is used to map the business workflow to an enumerated state.
|
||||||
Initially the initiator creates a new state object which receives a new
|
Initially the initiator creates a new state object which receives a new
|
||||||
``UniqueIdentifier`` in its ``linearId`` property and a starting
|
``UniqueIdentifier`` in its ``linearId`` property and a starting
|
||||||
workflow state of ``NEW``. The ``Contract.verify`` method is written to
|
workflow state of ``NEW``. The ``Contract.verify`` method is written to
|
||||||
allow the initiator to sign this initial transaction and send it to the
|
allow the initiator to sign this initial transaction and send it to the
|
||||||
other party. This pattern ensures that a permanent copy is recorded on
|
other party. This pattern ensures that a permanent copy is recorded on
|
||||||
both ledgers for audit purposes, but the state is prevented from being
|
both ledgers for audit purposes, but the state is prevented from being
|
||||||
maliciously put in an approved state. The subsequent workflow steps then
|
maliciously put in an approved state. The subsequent workflow steps then
|
||||||
follow with transactions that consume the state as inputs on one side
|
follow with transactions that consume the state as inputs on one side
|
||||||
and output a new version with whatever state updates, or amendments
|
and output a new version with whatever state updates, or amendments
|
||||||
match to the business process, the ``linearId`` being preserved across
|
match to the business process, the ``linearId`` being preserved across
|
||||||
the changes. Attached ``Command`` objects help the verify method
|
the changes. Attached ``Command`` objects help the verify method
|
||||||
restrict changes to appropriate fields and signers at each step in the
|
restrict changes to appropriate fields and signers at each step in the
|
||||||
workflow. In this it is typical to have both parties sign the change
|
workflow. In this it is typical to have both parties sign the change
|
||||||
transactions, but it can be valid to allow unilateral signing, if for instance
|
transactions, but it can be valid to allow unilateral signing, if for instance
|
||||||
one side could block a rejection. Commonly the manual initiator of these
|
one side could block a rejection. Commonly the manual initiator of these
|
||||||
workflows will query the Vault for states of the right contract type and
|
workflows will query the Vault for states of the right contract type and
|
||||||
in the right workflow state over the RPC interface. The RPC will then
|
in the right workflow state over the RPC interface. The RPC will then
|
||||||
initiate the relevant flow using ``StateRef``, or ``linearId`` values as
|
initiate the relevant flow using ``StateRef``, or ``linearId`` values as
|
||||||
parameters to the flow to identify the states being operated upon. Thus
|
parameters to the flow to identify the states being operated upon. Thus
|
||||||
code to gather the latest input state would be:
|
code to gather the latest input state would be:
|
||||||
|
|
||||||
@ -177,51 +177,51 @@ code to gather the latest input state would be:
|
|||||||
Generating Commands
|
Generating Commands
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
For the commands that will be added to the transaction, these will need
|
For the commands that will be added to the transaction, these will need
|
||||||
to correctly reflect the task at hand. These must match because inside
|
to correctly reflect the task at hand. These must match because inside
|
||||||
the ``Contract.verify`` method the command will be used to select the
|
the ``Contract.verify`` method the command will be used to select the
|
||||||
validation code path. The ``Contract.verify`` method will then restrict
|
validation code path. The ``Contract.verify`` method will then restrict
|
||||||
the allowed contents of the transaction to reflect this context. Typical
|
the allowed contents of the transaction to reflect this context. Typical
|
||||||
restrictions might include that the input cash amount must equal the
|
restrictions might include that the input cash amount must equal the
|
||||||
output cash amount, or that a workflow step is only allowed to change
|
output cash amount, or that a workflow step is only allowed to change
|
||||||
the status field. Sometimes, the command may capture some data too e.g.
|
the status field. Sometimes, the command may capture some data too e.g.
|
||||||
the foreign exchange rate, or the identity of one party, or the StateRef
|
the foreign exchange rate, or the identity of one party, or the StateRef
|
||||||
of the specific input that originates the command in a bulk operation.
|
of the specific input that originates the command in a bulk operation.
|
||||||
This data will be used to further aid the ``Contract.verify``, because
|
This data will be used to further aid the ``Contract.verify``, because
|
||||||
to ensure consistent, secure and reproducible behaviour in a distributed
|
to ensure consistent, secure and reproducible behaviour in a distributed
|
||||||
environment the ``Contract.verify``, transaction is the only allowed to
|
environment the ``Contract.verify``, transaction is the only allowed to
|
||||||
use the content of the transaction to decide validity.
|
use the content of the transaction to decide validity.
|
||||||
|
|
||||||
Another essential requirement for commands is that the correct set of
|
Another essential requirement for commands is that the correct set of
|
||||||
``CompositeKeys`` are added to the Command on the builder, which will be
|
``CompositeKeys`` are added to the Command on the builder, which will be
|
||||||
used to form the set of required signers on the final validated
|
used to form the set of required signers on the final validated
|
||||||
transaction. These must correctly align with the expectations of the
|
transaction. These must correctly align with the expectations of the
|
||||||
``Contract.verify`` method, which should be written to defensively check
|
``Contract.verify`` method, which should be written to defensively check
|
||||||
this. In particular, it is expected that at minimum the owner of an
|
this. In particular, it is expected that at minimum the owner of an
|
||||||
asset would have to be signing to permission transfer of that asset. In
|
asset would have to be signing to permission transfer of that asset. In
|
||||||
addition, other signatories will often be required e.g. an Oracle
|
addition, other signatories will often be required e.g. an Oracle
|
||||||
identity for an Oracle command, or both parties when there is an
|
identity for an Oracle command, or both parties when there is an
|
||||||
exchange of assets.
|
exchange of assets.
|
||||||
|
|
||||||
Generating Outputs
|
Generating Outputs
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
Having located a set of ``StateAndRefs`` as the transaction inputs, the
|
Having located a set of ``StateAndRefs`` as the transaction inputs, the
|
||||||
flow has to generate the output states. Typically, this is a simple call
|
flow has to generate the output states. Typically, this is a simple call
|
||||||
to the Kotlin ``copy`` method to modify the few fields that will
|
to the Kotlin ``copy`` method to modify the few fields that will
|
||||||
transitioned in the transaction. The contract code may provide a
|
transitioned in the transaction. The contract code may provide a
|
||||||
``generateXXX`` method to help with this process if the task is more
|
``generateXXX`` method to help with this process if the task is more
|
||||||
complicated. With a workflow state a slightly modified copy state is
|
complicated. With a workflow state a slightly modified copy state is
|
||||||
usually sufficient, especially as it is expected that we wish to preserve
|
usually sufficient, especially as it is expected that we wish to preserve
|
||||||
the ``linearId`` between state revisions, so that Vault queries can find
|
the ``linearId`` between state revisions, so that Vault queries can find
|
||||||
the latest revision.
|
the latest revision.
|
||||||
|
|
||||||
For fungible contract states such as ``Cash`` it is common to distribute
|
For fungible contract states such as ``Cash`` it is common to distribute
|
||||||
and split the total amount e.g. to produce a remaining balance output
|
and split the total amount e.g. to produce a remaining balance output
|
||||||
state for the original owner when breaking up a large amount input
|
state for the original owner when breaking up a large amount input
|
||||||
state. Remember that the result of a successful transaction is always to
|
state. Remember that the result of a successful transaction is always to
|
||||||
fully consume/spend the input states, so this is required to conserve
|
fully consume/spend the input states, so this is required to conserve
|
||||||
the total cash. For example from the demo code:
|
the total cash. For example from the demo code:
|
||||||
|
|
||||||
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt
|
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt
|
||||||
:language: kotlin
|
:language: kotlin
|
||||||
@ -231,15 +231,13 @@ the total cash. For example from the demo code:
|
|||||||
Building the WireTransaction
|
Building the WireTransaction
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
Having gathered all the ingredients for the transaction we now need to
|
Having gathered all the ingredients for the transaction we now need to
|
||||||
use a ``TransactionBuilder`` to construct the full ``WireTransaction``.
|
use a ``TransactionBuilder`` to construct the full ``WireTransaction``.
|
||||||
The initial ``TransactionBuilder`` should be created by calling the
|
The initial ``TransactionBuilder`` should be created by calling the
|
||||||
``TransactionType.General.Builder`` method. (The other
|
``TransactionBuilder`` method. At this point the
|
||||||
``TransactionBuilder`` implementation is only used for the ``NotaryChange`` flow where
|
Notary to associate with the states should be recorded. Then we keep
|
||||||
``ContractStates`` need moving to a different Notary.) At this point the
|
adding inputs, outputs, commands and attachments to fill the
|
||||||
Notary to associate with the states should be recorded. Then we keep
|
transaction. Examples of this process are:
|
||||||
adding inputs, outputs, commands and attachments to fill the
|
|
||||||
transaction. Examples of this process are:
|
|
||||||
|
|
||||||
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt
|
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt
|
||||||
:language: kotlin
|
:language: kotlin
|
||||||
@ -254,51 +252,51 @@ transaction. Examples of this process are:
|
|||||||
Completing the SignedTransaction
|
Completing the SignedTransaction
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
Having created an initial ``WireTransaction`` and converted this to an
|
Having created an initial ``WireTransaction`` and converted this to an
|
||||||
initial ``SignedTransaction`` the process of verifying and forming a
|
initial ``SignedTransaction`` the process of verifying and forming a
|
||||||
full ``SignedTransaction`` begins and then completes with the
|
full ``SignedTransaction`` begins and then completes with the
|
||||||
notarisation. In practice this is a relatively stereotypical process,
|
notarisation. In practice this is a relatively stereotypical process,
|
||||||
because assuming the ``WireTransaction`` is correctly constructed the
|
because assuming the ``WireTransaction`` is correctly constructed the
|
||||||
verification should be immediate. However, it is also important to
|
verification should be immediate. However, it is also important to
|
||||||
recheck the business details of any data received back from an external
|
recheck the business details of any data received back from an external
|
||||||
node, because a malicious party could always modify the contents before
|
node, because a malicious party could always modify the contents before
|
||||||
returning the transaction. Each remote flow should therefore check as
|
returning the transaction. Each remote flow should therefore check as
|
||||||
much as possible of the initial ``SignedTransaction`` inside the ``unwrap`` of
|
much as possible of the initial ``SignedTransaction`` inside the ``unwrap`` of
|
||||||
the receive before agreeing to sign. Any issues should immediately throw
|
the receive before agreeing to sign. Any issues should immediately throw
|
||||||
an exception to abort the flow. Similarly the originator, should always
|
an exception to abort the flow. Similarly the originator, should always
|
||||||
apply any new signatures to its original proposal to ensure the contents
|
apply any new signatures to its original proposal to ensure the contents
|
||||||
of the transaction has not been altered by the remote parties.
|
of the transaction has not been altered by the remote parties.
|
||||||
|
|
||||||
The typical code therefore checks the received ``SignedTransaction``
|
The typical code therefore checks the received ``SignedTransaction``
|
||||||
using the ``verifySignaturesExcept`` method, excluding itself, the
|
using the ``verifySignaturesExcept`` method, excluding itself, the
|
||||||
notary and any other parties yet to apply their signature. The contents of the
|
notary and any other parties yet to apply their signature. The contents of the
|
||||||
``WireTransaction`` inside the ``SignedTransaction`` should be fully
|
``WireTransaction`` inside the ``SignedTransaction`` should be fully
|
||||||
verified further by expanding with ``toLedgerTransaction`` and calling
|
verified further by expanding with ``toLedgerTransaction`` and calling
|
||||||
``verify``. Further context specific and business checks should then be
|
``verify``. Further context specific and business checks should then be
|
||||||
made, because the ``Contract.verify`` is not allowed to access external
|
made, because the ``Contract.verify`` is not allowed to access external
|
||||||
context. For example the flow may need to check that the parties are the
|
context. For example the flow may need to check that the parties are the
|
||||||
right ones, or that the ``Command`` present on the transaction is as
|
right ones, or that the ``Command`` present on the transaction is as
|
||||||
expected for this specific flow. An example of this from the demo code is:
|
expected for this specific flow. An example of this from the demo code is:
|
||||||
|
|
||||||
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt
|
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt
|
||||||
:language: kotlin
|
:language: kotlin
|
||||||
:start-after: DOCSTART 3
|
:start-after: DOCSTART 3
|
||||||
:end-before: DOCEND 3
|
:end-before: DOCEND 3
|
||||||
|
|
||||||
After verification the remote flow will return its signature to the
|
After verification the remote flow will return its signature to the
|
||||||
originator. The originator should apply that signature to the starting
|
originator. The originator should apply that signature to the starting
|
||||||
``SignedTransaction`` and recheck the signatures match.
|
``SignedTransaction`` and recheck the signatures match.
|
||||||
|
|
||||||
Committing the Transaction
|
Committing the Transaction
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
Once all the party signatures are applied to the SignedTransaction the
|
Once all the party signatures are applied to the SignedTransaction the
|
||||||
final step is notarisation. This involves calling ``NotaryFlow.Client``
|
final step is notarisation. This involves calling ``NotaryFlow.Client``
|
||||||
to confirm the transaction, consume the inputs and return its confirming
|
to confirm the transaction, consume the inputs and return its confirming
|
||||||
signature. Then the flow should ensure that all nodes end with all
|
signature. Then the flow should ensure that all nodes end with all
|
||||||
signatures and that they call ``ServiceHub.recordTransactions``. The
|
signatures and that they call ``ServiceHub.recordTransactions``. The
|
||||||
code for this is standardised in the ``FinalityFlow``, or more explicitly
|
code for this is standardised in the ``FinalityFlow``, or more explicitly
|
||||||
an example is:
|
an example is:
|
||||||
|
|
||||||
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt
|
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt
|
||||||
:language: kotlin
|
:language: kotlin
|
||||||
@ -308,19 +306,19 @@ an example is:
|
|||||||
Partially Visible Transactions
|
Partially Visible Transactions
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
The discussion so far has assumed that the parties need full visibility
|
The discussion so far has assumed that the parties need full visibility
|
||||||
of the transaction to sign. However, there may be situations where each
|
of the transaction to sign. However, there may be situations where each
|
||||||
party needs to store private data for audit purposes, or for evidence to
|
party needs to store private data for audit purposes, or for evidence to
|
||||||
a regulator, but does not wish to share that with the other trading
|
a regulator, but does not wish to share that with the other trading
|
||||||
partner. The tear-off/Merkle tree support in Corda allows flows to send
|
partner. The tear-off/Merkle tree support in Corda allows flows to send
|
||||||
portions of the full transaction to restrict visibility to remote
|
portions of the full transaction to restrict visibility to remote
|
||||||
parties. To do this one can use the
|
parties. To do this one can use the
|
||||||
``WireTransaction.buildFilteredTransaction`` extension method to produce
|
``WireTransaction.buildFilteredTransaction`` extension method to produce
|
||||||
a ``FilteredTransaction``. The elements of the ``SignedTransaction``
|
a ``FilteredTransaction``. The elements of the ``SignedTransaction``
|
||||||
which we wish to be hide will be replaced with their secure hash. The
|
which we wish to be hide will be replaced with their secure hash. The
|
||||||
overall transaction txid is still provable from the
|
overall transaction txid is still provable from the
|
||||||
``FilteredTransaction`` preventing change of the private data, but we do
|
``FilteredTransaction`` preventing change of the private data, but we do
|
||||||
not expose that data to the other node directly. A full example of this
|
not expose that data to the other node directly. A full example of this
|
||||||
can be found in the ``NodeInterestRates`` Oracle code from the
|
can be found in the ``NodeInterestRates`` Oracle code from the
|
||||||
``irs-demo`` project which interacts with the ``RatesFixFlow`` flow.
|
``irs-demo`` project which interacts with the ``RatesFixFlow`` flow.
|
||||||
Also, refer to the :doc:`merkle-trees` documentation.
|
Also, refer to the :doc:`merkle-trees` documentation.
|
||||||
|
@ -39,7 +39,7 @@ Then we initialise the transaction builder:
|
|||||||
|
|
||||||
.. sourcecode:: kotlin
|
.. sourcecode:: kotlin
|
||||||
|
|
||||||
val builder: TransactionBuilder = TransactionType.General.Builder(notary = ourNotary)
|
val builder: TransactionBuilder = TransactionBuilder(notary = ourNotary)
|
||||||
|
|
||||||
For any output state we add to this transaction builder, ``ourNotary`` will be assigned as its notary.
|
For any output state we add to this transaction builder, ``ourNotary`` will be assigned as its notary.
|
||||||
Next we create a state object and assign ourselves as the owner. For this example we'll use a
|
Next we create a state object and assign ourselves as the owner. For this example we'll use a
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package net.corda.contracts
|
package net.corda.contracts.isolated
|
||||||
|
|
||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
@ -31,7 +31,7 @@ class AnotherDummyContract : Contract, net.corda.core.node.DummyContractBackdoor
|
|||||||
|
|
||||||
override fun generateInitial(owner: PartyAndReference, magicNumber: Int, notary: Party): TransactionBuilder {
|
override fun generateInitial(owner: PartyAndReference, magicNumber: Int, notary: Party): TransactionBuilder {
|
||||||
val state = State(magicNumber)
|
val state = State(magicNumber)
|
||||||
return TransactionType.General.Builder(notary = notary).withItems(state, Command(Commands.Create(), owner.party.owningKey))
|
return TransactionBuilder(notary).withItems(state, Command(Commands.Create(), owner.party.owningKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun inspectState(state: ContractState): Int = (state as State).magicNumber
|
override fun inspectState(state: ContractState): Int = (state as State).magicNumber
|
@ -316,7 +316,7 @@ public class JavaCommercialPaper implements Contract {
|
|||||||
public TransactionBuilder generateIssue(@NotNull PartyAndReference issuance, @NotNull Amount<Issued<Currency>> faceValue, @Nullable Instant maturityDate, @NotNull Party notary, Integer encumbrance) {
|
public TransactionBuilder generateIssue(@NotNull PartyAndReference issuance, @NotNull Amount<Issued<Currency>> faceValue, @Nullable Instant maturityDate, @NotNull Party notary, Integer encumbrance) {
|
||||||
State state = new State(issuance, issuance.getParty(), faceValue, maturityDate);
|
State state = new State(issuance, issuance.getParty(), faceValue, maturityDate);
|
||||||
TransactionState output = new TransactionState<>(state, notary, encumbrance);
|
TransactionState output = new TransactionState<>(state, notary, encumbrance);
|
||||||
return new TransactionType.General.Builder(notary).withItems(output, new Command(new Commands.Issue(), issuance.getParty().getOwningKey()));
|
return new TransactionBuilder(notary).withItems(output, new Command(new Commands.Issue(), issuance.getParty().getOwningKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TransactionBuilder generateIssue(@NotNull PartyAndReference issuance, @NotNull Amount<Issued<Currency>> faceValue, @Nullable Instant maturityDate, @NotNull Party notary) {
|
public TransactionBuilder generateIssue(@NotNull PartyAndReference issuance, @NotNull Amount<Issued<Currency>> faceValue, @Nullable Instant maturityDate, @NotNull Party notary) {
|
||||||
|
@ -200,7 +200,7 @@ class CommercialPaper : Contract {
|
|||||||
*/
|
*/
|
||||||
fun generateIssue(issuance: PartyAndReference, faceValue: Amount<Issued<Currency>>, maturityDate: Instant, notary: Party): TransactionBuilder {
|
fun generateIssue(issuance: PartyAndReference, faceValue: Amount<Issued<Currency>>, maturityDate: Instant, notary: Party): TransactionBuilder {
|
||||||
val state = TransactionState(State(issuance, issuance.party, faceValue, maturityDate), notary)
|
val state = TransactionState(State(issuance, issuance.party, faceValue, maturityDate), notary)
|
||||||
return TransactionType.General.Builder(notary = notary).withItems(state, Command(Commands.Issue(), issuance.party.owningKey))
|
return TransactionBuilder(notary).withItems(state, Command(Commands.Issue(), issuance.party.owningKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,7 +4,6 @@ import co.paralleluniverse.fibers.Suspendable
|
|||||||
import net.corda.contracts.asset.Cash
|
import net.corda.contracts.asset.Cash
|
||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
import net.corda.core.contracts.InsufficientBalanceException
|
import net.corda.core.contracts.InsufficientBalanceException
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.contracts.issuedBy
|
import net.corda.core.contracts.issuedBy
|
||||||
import net.corda.core.flows.StartableByRPC
|
import net.corda.core.flows.StartableByRPC
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
@ -36,7 +35,7 @@ class CashExitFlow(val amount: Amount<Currency>, val issueRef: OpaqueBytes, prog
|
|||||||
@Throws(CashException::class)
|
@Throws(CashException::class)
|
||||||
override fun call(): AbstractCashFlow.Result {
|
override fun call(): AbstractCashFlow.Result {
|
||||||
progressTracker.currentStep = GENERATING_TX
|
progressTracker.currentStep = GENERATING_TX
|
||||||
val builder: TransactionBuilder = TransactionType.General.Builder(notary = null as Party?)
|
val builder: TransactionBuilder = TransactionBuilder(notary = null as Party?)
|
||||||
val issuer = serviceHub.myInfo.legalIdentity.ref(issueRef)
|
val issuer = serviceHub.myInfo.legalIdentity.ref(issueRef)
|
||||||
val exitStates = serviceHub.vaultService.unconsumedStatesForSpending<Cash.State>(amount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference))
|
val exitStates = serviceHub.vaultService.unconsumedStatesForSpending<Cash.State>(amount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference))
|
||||||
val signers = try {
|
val signers = try {
|
||||||
|
@ -3,7 +3,6 @@ package net.corda.flows
|
|||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.contracts.asset.Cash
|
import net.corda.contracts.asset.Cash
|
||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.contracts.issuedBy
|
import net.corda.core.contracts.issuedBy
|
||||||
import net.corda.core.flows.FinalityFlow
|
import net.corda.core.flows.FinalityFlow
|
||||||
import net.corda.core.flows.StartableByRPC
|
import net.corda.core.flows.StartableByRPC
|
||||||
@ -50,7 +49,7 @@ class CashIssueFlow(val amount: Amount<Currency>,
|
|||||||
}
|
}
|
||||||
val anonymousRecipient = txIdentities[recipient]?.party ?: recipient
|
val anonymousRecipient = txIdentities[recipient]?.party ?: recipient
|
||||||
progressTracker.currentStep = GENERATING_TX
|
progressTracker.currentStep = GENERATING_TX
|
||||||
val builder: TransactionBuilder = TransactionType.General.Builder(notary = notary)
|
val builder: TransactionBuilder = TransactionBuilder(notary)
|
||||||
val issuer = serviceHub.myInfo.legalIdentity.ref(issueRef)
|
val issuer = serviceHub.myInfo.legalIdentity.ref(issueRef)
|
||||||
val signers = Cash().generateIssue(builder, amount.issuedBy(issuer), anonymousRecipient, notary)
|
val signers = Cash().generateIssue(builder, amount.issuedBy(issuer), anonymousRecipient, notary)
|
||||||
progressTracker.currentStep = SIGNING_TX
|
progressTracker.currentStep = SIGNING_TX
|
||||||
|
@ -3,7 +3,6 @@ package net.corda.flows
|
|||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
import net.corda.core.contracts.InsufficientBalanceException
|
import net.corda.core.contracts.InsufficientBalanceException
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.flows.StartableByRPC
|
import net.corda.core.flows.StartableByRPC
|
||||||
import net.corda.core.flows.TransactionKeyFlow
|
import net.corda.core.flows.TransactionKeyFlow
|
||||||
import net.corda.core.identity.AnonymousPartyAndPath
|
import net.corda.core.identity.AnonymousPartyAndPath
|
||||||
@ -43,7 +42,7 @@ open class CashPaymentFlow(
|
|||||||
}
|
}
|
||||||
val anonymousRecipient = txIdentities.get(recipient)?.party ?: recipient
|
val anonymousRecipient = txIdentities.get(recipient)?.party ?: recipient
|
||||||
progressTracker.currentStep = GENERATING_TX
|
progressTracker.currentStep = GENERATING_TX
|
||||||
val builder: TransactionBuilder = TransactionType.General.Builder(null as Party?)
|
val builder: TransactionBuilder = TransactionBuilder(null as Party?)
|
||||||
// TODO: Have some way of restricting this to states the caller controls
|
// TODO: Have some way of restricting this to states the caller controls
|
||||||
val (spendTX, keysForSigning) = try {
|
val (spendTX, keysForSigning) = try {
|
||||||
serviceHub.vaultService.generateSpend(
|
serviceHub.vaultService.generateSpend(
|
||||||
|
@ -178,7 +178,7 @@ object TwoPartyTradeFlow {
|
|||||||
|
|
||||||
@Suspendable
|
@Suspendable
|
||||||
private fun assembleSharedTX(tradeRequest: SellerTradeInfo): Pair<TransactionBuilder, List<PublicKey>> {
|
private fun assembleSharedTX(tradeRequest: SellerTradeInfo): Pair<TransactionBuilder, List<PublicKey>> {
|
||||||
val ptx = TransactionType.General.Builder(notary)
|
val ptx = TransactionBuilder(notary)
|
||||||
|
|
||||||
// Add input and output states for the movement of cash, by using the Cash contract to generate the states
|
// Add input and output states for the movement of cash, by using the Cash contract to generate the states
|
||||||
val (tx, cashSigningPubKeys) = serviceHub.vaultService.generateSpend(ptx, tradeRequest.price, tradeRequest.sellerOwner)
|
val (tx, cashSigningPubKeys) = serviceHub.vaultService.generateSpend(ptx, tradeRequest.price, tradeRequest.sellerOwner)
|
||||||
|
@ -10,6 +10,7 @@ import net.corda.core.node.services.Vault
|
|||||||
import net.corda.core.node.services.VaultService
|
import net.corda.core.node.services.VaultService
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.node.utilities.configureDatabase
|
import net.corda.node.utilities.configureDatabase
|
||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.node.MockServices
|
import net.corda.testing.node.MockServices
|
||||||
@ -263,7 +264,7 @@ class CommercialPaperTestsGeneric {
|
|||||||
databaseAlice.transaction {
|
databaseAlice.transaction {
|
||||||
// Alice pays $9000 to BigCorp to own some of their debt.
|
// Alice pays $9000 to BigCorp to own some of their debt.
|
||||||
moveTX = run {
|
moveTX = run {
|
||||||
val builder = TransactionType.General.Builder(DUMMY_NOTARY)
|
val builder = TransactionBuilder(DUMMY_NOTARY)
|
||||||
aliceVaultService.generateSpend(builder, 9000.DOLLARS, AnonymousParty(bigCorpServices.key.public))
|
aliceVaultService.generateSpend(builder, 9000.DOLLARS, AnonymousParty(bigCorpServices.key.public))
|
||||||
CommercialPaper().generateMove(builder, issueTx.tx.outRef(0), AnonymousParty(aliceServices.key.public))
|
CommercialPaper().generateMove(builder, issueTx.tx.outRef(0), AnonymousParty(aliceServices.key.public))
|
||||||
val ptx = aliceServices.signInitialTransaction(builder)
|
val ptx = aliceServices.signInitialTransaction(builder)
|
||||||
@ -284,7 +285,7 @@ class CommercialPaperTestsGeneric {
|
|||||||
|
|
||||||
databaseBigCorp.transaction {
|
databaseBigCorp.transaction {
|
||||||
fun makeRedeemTX(time: Instant): Pair<SignedTransaction, UUID> {
|
fun makeRedeemTX(time: Instant): Pair<SignedTransaction, UUID> {
|
||||||
val builder = TransactionType.General.Builder(DUMMY_NOTARY)
|
val builder = TransactionBuilder(DUMMY_NOTARY)
|
||||||
builder.setTimeWindow(time, 30.seconds)
|
builder.setTimeWindow(time, 30.seconds)
|
||||||
CommercialPaper().generateRedeem(builder, moveTX.tx.outRef(1), bigCorpVaultService)
|
CommercialPaper().generateRedeem(builder, moveTX.tx.outRef(1), bigCorpVaultService)
|
||||||
val ptx = aliceServices.signInitialTransaction(builder)
|
val ptx = aliceServices.signInitialTransaction(builder)
|
||||||
|
@ -9,6 +9,7 @@ import net.corda.core.identity.Party
|
|||||||
import net.corda.core.node.services.VaultService
|
import net.corda.core.node.services.VaultService
|
||||||
import net.corda.core.node.services.unconsumedStates
|
import net.corda.core.node.services.unconsumedStates
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.transactions.WireTransaction
|
import net.corda.core.transactions.WireTransaction
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.node.services.vault.NodeVaultService
|
import net.corda.node.services.vault.NodeVaultService
|
||||||
@ -155,7 +156,7 @@ class CashTests : TestDependencyInjectionBase() {
|
|||||||
fun generateIssueRaw() {
|
fun generateIssueRaw() {
|
||||||
initialiseTestSerialization()
|
initialiseTestSerialization()
|
||||||
// Test generation works.
|
// Test generation works.
|
||||||
val tx: WireTransaction = TransactionType.General.Builder(notary = null).apply {
|
val tx: WireTransaction = TransactionBuilder(notary = null).apply {
|
||||||
Cash().generateIssue(this, 100.DOLLARS `issued by` MINI_CORP.ref(12, 34), owner = AnonymousParty(DUMMY_PUBKEY_1), notary = DUMMY_NOTARY)
|
Cash().generateIssue(this, 100.DOLLARS `issued by` MINI_CORP.ref(12, 34), owner = AnonymousParty(DUMMY_PUBKEY_1), notary = DUMMY_NOTARY)
|
||||||
}.toWireTransaction()
|
}.toWireTransaction()
|
||||||
assertTrue(tx.inputs.isEmpty())
|
assertTrue(tx.inputs.isEmpty())
|
||||||
@ -172,7 +173,7 @@ class CashTests : TestDependencyInjectionBase() {
|
|||||||
initialiseTestSerialization()
|
initialiseTestSerialization()
|
||||||
// Test issuance from an issued amount
|
// Test issuance from an issued amount
|
||||||
val amount = 100.DOLLARS `issued by` MINI_CORP.ref(12, 34)
|
val amount = 100.DOLLARS `issued by` MINI_CORP.ref(12, 34)
|
||||||
val tx: WireTransaction = TransactionType.General.Builder(notary = null).apply {
|
val tx: WireTransaction = TransactionBuilder(notary = null).apply {
|
||||||
Cash().generateIssue(this, amount, owner = AnonymousParty(DUMMY_PUBKEY_1), notary = DUMMY_NOTARY)
|
Cash().generateIssue(this, amount, owner = AnonymousParty(DUMMY_PUBKEY_1), notary = DUMMY_NOTARY)
|
||||||
}.toWireTransaction()
|
}.toWireTransaction()
|
||||||
assertTrue(tx.inputs.isEmpty())
|
assertTrue(tx.inputs.isEmpty())
|
||||||
@ -244,13 +245,13 @@ class CashTests : TestDependencyInjectionBase() {
|
|||||||
fun `reject issuance with inputs`() {
|
fun `reject issuance with inputs`() {
|
||||||
initialiseTestSerialization()
|
initialiseTestSerialization()
|
||||||
// Issue some cash
|
// Issue some cash
|
||||||
var ptx = TransactionType.General.Builder(DUMMY_NOTARY)
|
var ptx = TransactionBuilder(DUMMY_NOTARY)
|
||||||
|
|
||||||
Cash().generateIssue(ptx, 100.DOLLARS `issued by` MINI_CORP.ref(12, 34), owner = MINI_CORP, notary = DUMMY_NOTARY)
|
Cash().generateIssue(ptx, 100.DOLLARS `issued by` MINI_CORP.ref(12, 34), owner = MINI_CORP, notary = DUMMY_NOTARY)
|
||||||
val tx = miniCorpServices.signInitialTransaction(ptx)
|
val tx = miniCorpServices.signInitialTransaction(ptx)
|
||||||
|
|
||||||
// Include the previously issued cash in a new issuance command
|
// Include the previously issued cash in a new issuance command
|
||||||
ptx = TransactionType.General.Builder(DUMMY_NOTARY)
|
ptx = TransactionBuilder(DUMMY_NOTARY)
|
||||||
ptx.addInputState(tx.tx.outRef<Cash.State>(0))
|
ptx.addInputState(tx.tx.outRef<Cash.State>(0))
|
||||||
Cash().generateIssue(ptx, 100.DOLLARS `issued by` MINI_CORP.ref(12, 34), owner = MINI_CORP, notary = DUMMY_NOTARY)
|
Cash().generateIssue(ptx, 100.DOLLARS `issued by` MINI_CORP.ref(12, 34), owner = MINI_CORP, notary = DUMMY_NOTARY)
|
||||||
}
|
}
|
||||||
@ -476,13 +477,13 @@ class CashTests : TestDependencyInjectionBase() {
|
|||||||
* Generate an exit transaction, removing some amount of cash from the ledger.
|
* Generate an exit transaction, removing some amount of cash from the ledger.
|
||||||
*/
|
*/
|
||||||
fun makeExit(amount: Amount<Currency>, corp: Party, depositRef: Byte = 1): WireTransaction {
|
fun makeExit(amount: Amount<Currency>, corp: Party, depositRef: Byte = 1): WireTransaction {
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY)
|
val tx = TransactionBuilder(DUMMY_NOTARY)
|
||||||
Cash().generateExit(tx, Amount(amount.quantity, Issued(corp.ref(depositRef), amount.token)), WALLET)
|
Cash().generateExit(tx, Amount(amount.quantity, Issued(corp.ref(depositRef), amount.token)), WALLET)
|
||||||
return tx.toWireTransaction()
|
return tx.toWireTransaction()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun makeSpend(amount: Amount<Currency>, dest: AbstractParty): WireTransaction {
|
fun makeSpend(amount: Amount<Currency>, dest: AbstractParty): WireTransaction {
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY)
|
val tx = TransactionBuilder(DUMMY_NOTARY)
|
||||||
database.transaction {
|
database.transaction {
|
||||||
vault.generateSpend(tx, amount, dest)
|
vault.generateSpend(tx, amount, dest)
|
||||||
}
|
}
|
||||||
@ -560,7 +561,7 @@ class CashTests : TestDependencyInjectionBase() {
|
|||||||
fun generateExitWithEmptyVault() {
|
fun generateExitWithEmptyVault() {
|
||||||
initialiseTestSerialization()
|
initialiseTestSerialization()
|
||||||
assertFailsWith<InsufficientBalanceException> {
|
assertFailsWith<InsufficientBalanceException> {
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY)
|
val tx = TransactionBuilder(DUMMY_NOTARY)
|
||||||
Cash().generateExit(tx, Amount(100, Issued(CHARLIE.ref(1), GBP)), emptyList())
|
Cash().generateExit(tx, Amount(100, Issued(CHARLIE.ref(1), GBP)), emptyList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -584,7 +585,7 @@ class CashTests : TestDependencyInjectionBase() {
|
|||||||
initialiseTestSerialization()
|
initialiseTestSerialization()
|
||||||
database.transaction {
|
database.transaction {
|
||||||
|
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY)
|
val tx = TransactionBuilder(DUMMY_NOTARY)
|
||||||
vault.generateSpend(tx, 80.DOLLARS, ALICE, setOf(MINI_CORP))
|
vault.generateSpend(tx, 80.DOLLARS, ALICE, setOf(MINI_CORP))
|
||||||
|
|
||||||
assertEquals(vaultStatesUnconsumed.elementAt(2).ref, tx.inputStates()[0])
|
assertEquals(vaultStatesUnconsumed.elementAt(2).ref, tx.inputStates()[0])
|
||||||
|
@ -8,6 +8,7 @@ import net.corda.core.crypto.SecureHash
|
|||||||
import net.corda.core.crypto.testing.NULL_PARTY
|
import net.corda.core.crypto.testing.NULL_PARTY
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.AnonymousParty
|
import net.corda.core.identity.AnonymousParty
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.NonEmptySet
|
import net.corda.core.utilities.NonEmptySet
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.utilities.days
|
import net.corda.core.utilities.days
|
||||||
@ -135,7 +136,7 @@ class ObligationTests {
|
|||||||
|
|
||||||
initialiseTestSerialization()
|
initialiseTestSerialization()
|
||||||
// Test generation works.
|
// Test generation works.
|
||||||
val tx = TransactionType.General.Builder(notary = null).apply {
|
val tx = TransactionBuilder(notary = null).apply {
|
||||||
Obligation<Currency>().generateIssue(this, MINI_CORP, megaCorpDollarSettlement, 100.DOLLARS.quantity,
|
Obligation<Currency>().generateIssue(this, MINI_CORP, megaCorpDollarSettlement, 100.DOLLARS.quantity,
|
||||||
beneficiary = CHARLIE, notary = DUMMY_NOTARY)
|
beneficiary = CHARLIE, notary = DUMMY_NOTARY)
|
||||||
}.toWireTransaction()
|
}.toWireTransaction()
|
||||||
@ -214,14 +215,14 @@ class ObligationTests {
|
|||||||
fun `reject issuance with inputs`() {
|
fun `reject issuance with inputs`() {
|
||||||
initialiseTestSerialization()
|
initialiseTestSerialization()
|
||||||
// Issue some obligation
|
// Issue some obligation
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY).apply {
|
val tx = TransactionBuilder(DUMMY_NOTARY).apply {
|
||||||
Obligation<Currency>().generateIssue(this, MINI_CORP, megaCorpDollarSettlement, 100.DOLLARS.quantity,
|
Obligation<Currency>().generateIssue(this, MINI_CORP, megaCorpDollarSettlement, 100.DOLLARS.quantity,
|
||||||
beneficiary = MINI_CORP, notary = DUMMY_NOTARY)
|
beneficiary = MINI_CORP, notary = DUMMY_NOTARY)
|
||||||
}.toWireTransaction()
|
}.toWireTransaction()
|
||||||
|
|
||||||
|
|
||||||
// Include the previously issued obligation in a new issuance command
|
// Include the previously issued obligation in a new issuance command
|
||||||
val ptx = TransactionType.General.Builder(DUMMY_NOTARY)
|
val ptx = TransactionBuilder(DUMMY_NOTARY)
|
||||||
ptx.addInputState(tx.outRef<Obligation.State<Currency>>(0))
|
ptx.addInputState(tx.outRef<Obligation.State<Currency>>(0))
|
||||||
Obligation<Currency>().generateIssue(ptx, MINI_CORP, megaCorpDollarSettlement, 100.DOLLARS.quantity,
|
Obligation<Currency>().generateIssue(ptx, MINI_CORP, megaCorpDollarSettlement, 100.DOLLARS.quantity,
|
||||||
beneficiary = MINI_CORP, notary = DUMMY_NOTARY)
|
beneficiary = MINI_CORP, notary = DUMMY_NOTARY)
|
||||||
@ -233,7 +234,7 @@ class ObligationTests {
|
|||||||
initialiseTestSerialization()
|
initialiseTestSerialization()
|
||||||
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)
|
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)
|
||||||
val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE)
|
val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE)
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY).apply {
|
val tx = TransactionBuilder(DUMMY_NOTARY).apply {
|
||||||
Obligation<Currency>().generateCloseOutNetting(this, ALICE, obligationAliceToBob, obligationBobToAlice)
|
Obligation<Currency>().generateCloseOutNetting(this, ALICE, obligationAliceToBob, obligationBobToAlice)
|
||||||
}.toWireTransaction()
|
}.toWireTransaction()
|
||||||
assertEquals(0, tx.outputs.size)
|
assertEquals(0, tx.outputs.size)
|
||||||
@ -245,7 +246,7 @@ class ObligationTests {
|
|||||||
initialiseTestSerialization()
|
initialiseTestSerialization()
|
||||||
val obligationAliceToBob = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(ALICE, BOB)
|
val obligationAliceToBob = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(ALICE, BOB)
|
||||||
val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE)
|
val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE)
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY).apply {
|
val tx = TransactionBuilder(DUMMY_NOTARY).apply {
|
||||||
Obligation<Currency>().generateCloseOutNetting(this, ALICE, obligationAliceToBob, obligationBobToAlice)
|
Obligation<Currency>().generateCloseOutNetting(this, ALICE, obligationAliceToBob, obligationBobToAlice)
|
||||||
}.toWireTransaction()
|
}.toWireTransaction()
|
||||||
assertEquals(1, tx.outputs.size)
|
assertEquals(1, tx.outputs.size)
|
||||||
@ -260,7 +261,7 @@ class ObligationTests {
|
|||||||
initialiseTestSerialization()
|
initialiseTestSerialization()
|
||||||
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)
|
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)
|
||||||
val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE)
|
val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE)
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY).apply {
|
val tx = TransactionBuilder(DUMMY_NOTARY).apply {
|
||||||
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBob.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice)
|
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBob.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice)
|
||||||
}.toWireTransaction()
|
}.toWireTransaction()
|
||||||
assertEquals(0, tx.outputs.size)
|
assertEquals(0, tx.outputs.size)
|
||||||
@ -272,7 +273,7 @@ class ObligationTests {
|
|||||||
initialiseTestSerialization()
|
initialiseTestSerialization()
|
||||||
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)
|
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)
|
||||||
val obligationBobToAlice = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(BOB, ALICE)
|
val obligationBobToAlice = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(BOB, ALICE)
|
||||||
val tx = TransactionType.General.Builder(null).apply {
|
val tx = TransactionBuilder(null).apply {
|
||||||
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBob.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice)
|
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBob.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice)
|
||||||
}.toWireTransaction()
|
}.toWireTransaction()
|
||||||
assertEquals(1, tx.outputs.size)
|
assertEquals(1, tx.outputs.size)
|
||||||
@ -289,7 +290,7 @@ class ObligationTests {
|
|||||||
val dueBefore = TEST_TX_TIME - 7.days
|
val dueBefore = TEST_TX_TIME - 7.days
|
||||||
|
|
||||||
// Generate a transaction issuing the obligation.
|
// Generate a transaction issuing the obligation.
|
||||||
var tx = TransactionType.General.Builder(null).apply {
|
var tx = TransactionBuilder(null).apply {
|
||||||
val amount = Amount(100, Issued(defaultIssuer, USD))
|
val amount = Amount(100, Issued(defaultIssuer, USD))
|
||||||
Obligation<Currency>().generateCashIssue(this, ALICE, amount, dueBefore,
|
Obligation<Currency>().generateCashIssue(this, ALICE, amount, dueBefore,
|
||||||
beneficiary = MINI_CORP, notary = DUMMY_NOTARY)
|
beneficiary = MINI_CORP, notary = DUMMY_NOTARY)
|
||||||
@ -298,7 +299,7 @@ class ObligationTests {
|
|||||||
var stateAndRef = stx.tx.outRef<Obligation.State<Currency>>(0)
|
var stateAndRef = stx.tx.outRef<Obligation.State<Currency>>(0)
|
||||||
|
|
||||||
// Now generate a transaction marking the obligation as having defaulted
|
// Now generate a transaction marking the obligation as having defaulted
|
||||||
tx = TransactionType.General.Builder(DUMMY_NOTARY).apply {
|
tx = TransactionBuilder(DUMMY_NOTARY).apply {
|
||||||
Obligation<Currency>().generateSetLifecycle(this, listOf(stateAndRef), Lifecycle.DEFAULTED, DUMMY_NOTARY)
|
Obligation<Currency>().generateSetLifecycle(this, listOf(stateAndRef), Lifecycle.DEFAULTED, DUMMY_NOTARY)
|
||||||
}
|
}
|
||||||
var ptx = miniCorpServices.signInitialTransaction(tx, MINI_CORP_PUBKEY)
|
var ptx = miniCorpServices.signInitialTransaction(tx, MINI_CORP_PUBKEY)
|
||||||
@ -310,7 +311,7 @@ class ObligationTests {
|
|||||||
|
|
||||||
// And set it back
|
// And set it back
|
||||||
stateAndRef = stx.tx.outRef<Obligation.State<Currency>>(0)
|
stateAndRef = stx.tx.outRef<Obligation.State<Currency>>(0)
|
||||||
tx = TransactionType.General.Builder(DUMMY_NOTARY).apply {
|
tx = TransactionBuilder(DUMMY_NOTARY).apply {
|
||||||
Obligation<Currency>().generateSetLifecycle(this, listOf(stateAndRef), Lifecycle.NORMAL, DUMMY_NOTARY)
|
Obligation<Currency>().generateSetLifecycle(this, listOf(stateAndRef), Lifecycle.NORMAL, DUMMY_NOTARY)
|
||||||
}
|
}
|
||||||
ptx = miniCorpServices.signInitialTransaction(tx)
|
ptx = miniCorpServices.signInitialTransaction(tx)
|
||||||
@ -324,18 +325,18 @@ class ObligationTests {
|
|||||||
@Test
|
@Test
|
||||||
fun `generate settlement transaction`() {
|
fun `generate settlement transaction`() {
|
||||||
initialiseTestSerialization()
|
initialiseTestSerialization()
|
||||||
val cashTx = TransactionType.General.Builder(null).apply {
|
val cashTx = TransactionBuilder(null).apply {
|
||||||
Cash().generateIssue(this, 100.DOLLARS `issued by` defaultIssuer, MINI_CORP, DUMMY_NOTARY)
|
Cash().generateIssue(this, 100.DOLLARS `issued by` defaultIssuer, MINI_CORP, DUMMY_NOTARY)
|
||||||
}.toWireTransaction()
|
}.toWireTransaction()
|
||||||
|
|
||||||
// Generate a transaction issuing the obligation
|
// Generate a transaction issuing the obligation
|
||||||
val obligationTx = TransactionType.General.Builder(null).apply {
|
val obligationTx = TransactionBuilder(null).apply {
|
||||||
Obligation<Currency>().generateIssue(this, MINI_CORP, megaCorpDollarSettlement, 100.DOLLARS.quantity,
|
Obligation<Currency>().generateIssue(this, MINI_CORP, megaCorpDollarSettlement, 100.DOLLARS.quantity,
|
||||||
beneficiary = MINI_CORP, notary = DUMMY_NOTARY)
|
beneficiary = MINI_CORP, notary = DUMMY_NOTARY)
|
||||||
}.toWireTransaction()
|
}.toWireTransaction()
|
||||||
|
|
||||||
// Now generate a transaction settling the obligation
|
// Now generate a transaction settling the obligation
|
||||||
val settleTx = TransactionType.General.Builder(DUMMY_NOTARY).apply {
|
val settleTx = TransactionBuilder(DUMMY_NOTARY).apply {
|
||||||
Obligation<Currency>().generateSettle(this, listOf(obligationTx.outRef(0)), listOf(cashTx.outRef(0)), Cash.Commands.Move(), DUMMY_NOTARY)
|
Obligation<Currency>().generateSettle(this, listOf(obligationTx.outRef(0)), listOf(cashTx.outRef(0)), Cash.Commands.Move(), DUMMY_NOTARY)
|
||||||
}.toWireTransaction()
|
}.toWireTransaction()
|
||||||
assertEquals(2, settleTx.inputs.size)
|
assertEquals(2, settleTx.inputs.size)
|
||||||
|
@ -8,7 +8,6 @@ import net.corda.contracts.asset.Cash
|
|||||||
import net.corda.core.contracts.Command
|
import net.corda.core.contracts.Command
|
||||||
import net.corda.core.contracts.CommandData
|
import net.corda.core.contracts.CommandData
|
||||||
import net.corda.core.contracts.ContractState
|
import net.corda.core.contracts.ContractState
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.crypto.testing.NullSignature
|
import net.corda.core.crypto.testing.NullSignature
|
||||||
import net.corda.core.identity.AnonymousParty
|
import net.corda.core.identity.AnonymousParty
|
||||||
import net.corda.core.testing.*
|
import net.corda.core.testing.*
|
||||||
|
@ -3,7 +3,6 @@ package net.corda.node.services
|
|||||||
import com.nhaarman.mockito_kotlin.whenever
|
import com.nhaarman.mockito_kotlin.whenever
|
||||||
import net.corda.core.contracts.ContractState
|
import net.corda.core.contracts.ContractState
|
||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.StateRef
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.composite.CompositeKey
|
import net.corda.core.crypto.composite.CompositeKey
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
@ -13,6 +12,7 @@ import net.corda.core.flows.NotaryFlow
|
|||||||
import net.corda.core.getOrThrow
|
import net.corda.core.getOrThrow
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.Try
|
import net.corda.core.utilities.Try
|
||||||
import net.corda.node.internal.AbstractNode
|
import net.corda.node.internal.AbstractNode
|
||||||
@ -138,8 +138,8 @@ class BFTNotaryServiceTests {
|
|||||||
private fun AbstractNode.signInitialTransaction(
|
private fun AbstractNode.signInitialTransaction(
|
||||||
notary: Party,
|
notary: Party,
|
||||||
makeUnique: Boolean = false,
|
makeUnique: Boolean = false,
|
||||||
block: TransactionType.General.Builder.() -> Any?
|
block: TransactionBuilder.() -> Any?
|
||||||
) = services.signInitialTransaction(TransactionType.General.Builder(notary).apply {
|
) = services.signInitialTransaction(TransactionBuilder(notary).apply {
|
||||||
block()
|
block()
|
||||||
if (makeUnique) {
|
if (makeUnique) {
|
||||||
addAttachment(SecureHash.randomSHA256())
|
addAttachment(SecureHash.randomSHA256())
|
||||||
|
@ -3,13 +3,13 @@ package net.corda.node.services
|
|||||||
import com.google.common.util.concurrent.Futures
|
import com.google.common.util.concurrent.Futures
|
||||||
import net.corda.core.contracts.StateAndRef
|
import net.corda.core.contracts.StateAndRef
|
||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.StateRef
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.flows.NotaryError
|
import net.corda.core.flows.NotaryError
|
||||||
import net.corda.core.flows.NotaryException
|
import net.corda.core.flows.NotaryException
|
||||||
import net.corda.core.flows.NotaryFlow
|
import net.corda.core.flows.NotaryFlow
|
||||||
import net.corda.core.getOrThrow
|
import net.corda.core.getOrThrow
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.map
|
import net.corda.core.map
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.node.internal.AbstractNode
|
import net.corda.node.internal.AbstractNode
|
||||||
import net.corda.testing.DUMMY_BANK_A
|
import net.corda.testing.DUMMY_BANK_A
|
||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
@ -34,13 +34,13 @@ class RaftNotaryServiceTests : NodeBasedTest() {
|
|||||||
|
|
||||||
val inputState = issueState(bankA, notaryParty)
|
val inputState = issueState(bankA, notaryParty)
|
||||||
|
|
||||||
val firstTxBuilder = TransactionType.General.Builder(notaryParty).withItems(inputState)
|
val firstTxBuilder = TransactionBuilder(notaryParty).withItems(inputState)
|
||||||
val firstSpendTx = bankA.services.signInitialTransaction(firstTxBuilder)
|
val firstSpendTx = bankA.services.signInitialTransaction(firstTxBuilder)
|
||||||
|
|
||||||
val firstSpend = bankA.services.startFlow(NotaryFlow.Client(firstSpendTx))
|
val firstSpend = bankA.services.startFlow(NotaryFlow.Client(firstSpendTx))
|
||||||
firstSpend.resultFuture.getOrThrow()
|
firstSpend.resultFuture.getOrThrow()
|
||||||
|
|
||||||
val secondSpendBuilder = TransactionType.General.Builder(notaryParty).withItems(inputState).run {
|
val secondSpendBuilder = TransactionBuilder(notaryParty).withItems(inputState).run {
|
||||||
val dummyState = DummyContract.SingleOwnerState(0, bankA.info.legalIdentity)
|
val dummyState = DummyContract.SingleOwnerState(0, bankA.info.legalIdentity)
|
||||||
addOutputState(dummyState)
|
addOutputState(dummyState)
|
||||||
this
|
this
|
||||||
|
@ -137,7 +137,7 @@ class NotaryChangeTests {
|
|||||||
val stateB = DummyContract.SingleOwnerState(Random().nextInt(), owner.party)
|
val stateB = DummyContract.SingleOwnerState(Random().nextInt(), owner.party)
|
||||||
val stateC = DummyContract.SingleOwnerState(Random().nextInt(), owner.party)
|
val stateC = DummyContract.SingleOwnerState(Random().nextInt(), owner.party)
|
||||||
|
|
||||||
val tx = TransactionType.General.Builder(null).apply {
|
val tx = TransactionBuilder(null).apply {
|
||||||
addCommand(Command(DummyContract.Commands.Create(), owner.party.owningKey))
|
addCommand(Command(DummyContract.Commands.Create(), owner.party.owningKey))
|
||||||
addOutputState(stateA, notary, encumbrance = 2) // Encumbered by stateB
|
addOutputState(stateA, notary, encumbrance = 2) // Encumbered by stateB
|
||||||
addOutputState(stateC, notary)
|
addOutputState(stateC, notary)
|
||||||
|
@ -4,7 +4,6 @@ import io.requery.Persistable
|
|||||||
import io.requery.kotlin.eq
|
import io.requery.kotlin.eq
|
||||||
import io.requery.sql.KotlinEntityDataStore
|
import io.requery.sql.KotlinEntityDataStore
|
||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.StateRef
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.crypto.DigitalSignature
|
import net.corda.core.crypto.DigitalSignature
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.testing.NullPublicKey
|
import net.corda.core.crypto.testing.NullPublicKey
|
||||||
|
@ -9,6 +9,7 @@ import net.corda.core.identity.AbstractParty
|
|||||||
import net.corda.core.node.ServiceHub
|
import net.corda.core.node.ServiceHub
|
||||||
import net.corda.core.node.services.VaultService
|
import net.corda.core.node.services.VaultService
|
||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.testing.ALICE_KEY
|
import net.corda.testing.ALICE_KEY
|
||||||
import net.corda.testing.DUMMY_CA
|
import net.corda.testing.DUMMY_CA
|
||||||
import net.corda.testing.DUMMY_NOTARY
|
import net.corda.testing.DUMMY_NOTARY
|
||||||
@ -280,7 +281,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
|
|||||||
apply {
|
apply {
|
||||||
val freshKey = services.keyManagementService.freshKey()
|
val freshKey = services.keyManagementService.freshKey()
|
||||||
val state = TestState(FlowLogicRefFactoryImpl.createForRPC(TestFlowLogic::class.java, increment), instant)
|
val state = TestState(FlowLogicRefFactoryImpl.createForRPC(TestFlowLogic::class.java, increment), instant)
|
||||||
val builder = TransactionType.General.Builder(null).apply {
|
val builder = TransactionBuilder(null).apply {
|
||||||
addOutputState(state, DUMMY_NOTARY)
|
addOutputState(state, DUMMY_NOTARY)
|
||||||
addCommand(Command(), freshKey)
|
addCommand(Command(), freshKey)
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import net.corda.core.identity.AbstractParty
|
|||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.node.services.linearHeadsOfType
|
import net.corda.core.node.services.linearHeadsOfType
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.node.services.network.NetworkMapService
|
import net.corda.node.services.network.NetworkMapService
|
||||||
import net.corda.node.services.statemachine.StateMachineManager
|
import net.corda.node.services.statemachine.StateMachineManager
|
||||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||||
@ -57,7 +58,7 @@ class ScheduledFlowTests {
|
|||||||
serviceHub.myInfo.legalIdentity, destination)
|
serviceHub.myInfo.legalIdentity, destination)
|
||||||
|
|
||||||
val notary = serviceHub.networkMapCache.getAnyNotary()
|
val notary = serviceHub.networkMapCache.getAnyNotary()
|
||||||
val builder = TransactionType.General.Builder(notary)
|
val builder = TransactionBuilder(notary)
|
||||||
builder.withItems(scheduledState)
|
builder.withItems(scheduledState)
|
||||||
val tx = serviceHub.signInitialTransaction(builder)
|
val tx = serviceHub.signInitialTransaction(builder)
|
||||||
subFlow(FinalityFlow(tx, setOf(serviceHub.myInfo.legalIdentity)))
|
subFlow(FinalityFlow(tx, setOf(serviceHub.myInfo.legalIdentity)))
|
||||||
@ -77,7 +78,7 @@ class ScheduledFlowTests {
|
|||||||
require(!scheduledState.processed) { "State should not have been previously processed" }
|
require(!scheduledState.processed) { "State should not have been previously processed" }
|
||||||
val notary = state.state.notary
|
val notary = state.state.notary
|
||||||
val newStateOutput = scheduledState.copy(processed = true)
|
val newStateOutput = scheduledState.copy(processed = true)
|
||||||
val builder = TransactionType.General.Builder(notary)
|
val builder = TransactionBuilder(notary)
|
||||||
builder.withItems(state, newStateOutput)
|
builder.withItems(state, newStateOutput)
|
||||||
val tx = serviceHub.signInitialTransaction(builder)
|
val tx = serviceHub.signInitialTransaction(builder)
|
||||||
subFlow(FinalityFlow(tx, setOf(scheduledState.source, scheduledState.destination)))
|
subFlow(FinalityFlow(tx, setOf(scheduledState.source, scheduledState.destination)))
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package net.corda.node.services.persistence
|
package net.corda.node.services.persistence
|
||||||
|
|
||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.StateRef
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.crypto.DigitalSignature
|
import net.corda.core.crypto.DigitalSignature
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.testing.NullPublicKey
|
import net.corda.core.crypto.testing.NullPublicKey
|
||||||
|
@ -4,7 +4,6 @@ import co.paralleluniverse.fibers.Suspendable
|
|||||||
import net.corda.contracts.asset.Cash
|
import net.corda.contracts.asset.Cash
|
||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
import net.corda.core.contracts.Issued
|
import net.corda.core.contracts.Issued
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.contracts.USD
|
import net.corda.core.contracts.USD
|
||||||
import net.corda.core.flows.BroadcastTransactionFlow.NotifyTxRequest
|
import net.corda.core.flows.BroadcastTransactionFlow.NotifyTxRequest
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
@ -13,6 +12,7 @@ import net.corda.core.flows.InitiatingFlow
|
|||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.services.unconsumedStates
|
import net.corda.core.node.services.unconsumedStates
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.node.services.NotifyTransactionHandler
|
import net.corda.node.services.NotifyTransactionHandler
|
||||||
import net.corda.testing.DUMMY_NOTARY
|
import net.corda.testing.DUMMY_NOTARY
|
||||||
import net.corda.testing.MEGA_CORP
|
import net.corda.testing.MEGA_CORP
|
||||||
@ -50,7 +50,7 @@ class DataVendingServiceTests {
|
|||||||
mockNet.runNetwork()
|
mockNet.runNetwork()
|
||||||
|
|
||||||
// Generate an issuance transaction
|
// Generate an issuance transaction
|
||||||
val ptx = TransactionType.General.Builder(null)
|
val ptx = TransactionBuilder(null)
|
||||||
Cash().generateIssue(ptx, Amount(100, Issued(deposit, USD)), beneficiary, DUMMY_NOTARY)
|
Cash().generateIssue(ptx, Amount(100, Issued(deposit, USD)), beneficiary, DUMMY_NOTARY)
|
||||||
|
|
||||||
// Complete the cash transaction, and then manually relay it
|
// Complete the cash transaction, and then manually relay it
|
||||||
@ -80,7 +80,7 @@ class DataVendingServiceTests {
|
|||||||
mockNet.runNetwork()
|
mockNet.runNetwork()
|
||||||
|
|
||||||
// Generate an issuance transaction
|
// Generate an issuance transaction
|
||||||
val ptx = TransactionType.General.Builder(DUMMY_NOTARY)
|
val ptx = TransactionBuilder(DUMMY_NOTARY)
|
||||||
Cash().generateIssue(ptx, Amount(100, Issued(deposit, USD)), beneficiary, DUMMY_NOTARY)
|
Cash().generateIssue(ptx, Amount(100, Issued(deposit, USD)), beneficiary, DUMMY_NOTARY)
|
||||||
|
|
||||||
// The transaction tries issuing MEGA_CORP cash, but we aren't the issuer, so it's invalid
|
// The transaction tries issuing MEGA_CORP cash, but we aren't the issuer, so it's invalid
|
||||||
|
@ -3,7 +3,6 @@ package net.corda.node.services.transactions
|
|||||||
import com.google.common.util.concurrent.ListenableFuture
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
import net.corda.core.contracts.StateAndRef
|
import net.corda.core.contracts.StateAndRef
|
||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.StateRef
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.crypto.DigitalSignature
|
import net.corda.core.crypto.DigitalSignature
|
||||||
import net.corda.core.flows.NotaryError
|
import net.corda.core.flows.NotaryError
|
||||||
import net.corda.core.flows.NotaryException
|
import net.corda.core.flows.NotaryException
|
||||||
@ -12,6 +11,7 @@ import net.corda.core.getOrThrow
|
|||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.node.internal.AbstractNode
|
import net.corda.node.internal.AbstractNode
|
||||||
import net.corda.node.services.network.NetworkMapService
|
import net.corda.node.services.network.NetworkMapService
|
||||||
import net.corda.testing.DUMMY_NOTARY
|
import net.corda.testing.DUMMY_NOTARY
|
||||||
@ -50,7 +50,7 @@ class NotaryServiceTests {
|
|||||||
fun `should sign a unique transaction with a valid time-window`() {
|
fun `should sign a unique transaction with a valid time-window`() {
|
||||||
val stx = run {
|
val stx = run {
|
||||||
val inputState = issueState(clientNode)
|
val inputState = issueState(clientNode)
|
||||||
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
|
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState)
|
||||||
tx.setTimeWindow(Instant.now(), 30.seconds)
|
tx.setTimeWindow(Instant.now(), 30.seconds)
|
||||||
clientNode.services.signInitialTransaction(tx)
|
clientNode.services.signInitialTransaction(tx)
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ class NotaryServiceTests {
|
|||||||
fun `should sign a unique transaction without a time-window`() {
|
fun `should sign a unique transaction without a time-window`() {
|
||||||
val stx = run {
|
val stx = run {
|
||||||
val inputState = issueState(clientNode)
|
val inputState = issueState(clientNode)
|
||||||
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
|
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState)
|
||||||
clientNode.services.signInitialTransaction(tx)
|
clientNode.services.signInitialTransaction(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ class NotaryServiceTests {
|
|||||||
fun `should report error for transaction with an invalid time-window`() {
|
fun `should report error for transaction with an invalid time-window`() {
|
||||||
val stx = run {
|
val stx = run {
|
||||||
val inputState = issueState(clientNode)
|
val inputState = issueState(clientNode)
|
||||||
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
|
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState)
|
||||||
tx.setTimeWindow(Instant.now().plusSeconds(3600), 30.seconds)
|
tx.setTimeWindow(Instant.now().plusSeconds(3600), 30.seconds)
|
||||||
clientNode.services.signInitialTransaction(tx)
|
clientNode.services.signInitialTransaction(tx)
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ class NotaryServiceTests {
|
|||||||
fun `should sign identical transaction multiple times (signing is idempotent)`() {
|
fun `should sign identical transaction multiple times (signing is idempotent)`() {
|
||||||
val stx = run {
|
val stx = run {
|
||||||
val inputState = issueState(clientNode)
|
val inputState = issueState(clientNode)
|
||||||
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
|
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState)
|
||||||
clientNode.services.signInitialTransaction(tx)
|
clientNode.services.signInitialTransaction(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,11 +110,11 @@ class NotaryServiceTests {
|
|||||||
fun `should report conflict when inputs are reused across transactions`() {
|
fun `should report conflict when inputs are reused across transactions`() {
|
||||||
val inputState = issueState(clientNode)
|
val inputState = issueState(clientNode)
|
||||||
val stx = run {
|
val stx = run {
|
||||||
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
|
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState)
|
||||||
clientNode.services.signInitialTransaction(tx)
|
clientNode.services.signInitialTransaction(tx)
|
||||||
}
|
}
|
||||||
val stx2 = run {
|
val stx2 = run {
|
||||||
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
|
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState)
|
||||||
tx.addInputState(issueState(clientNode))
|
tx.addInputState(issueState(clientNode))
|
||||||
clientNode.services.signInitialTransaction(tx)
|
clientNode.services.signInitialTransaction(tx)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import com.google.common.util.concurrent.ListenableFuture
|
|||||||
import net.corda.core.contracts.Command
|
import net.corda.core.contracts.Command
|
||||||
import net.corda.core.contracts.StateAndRef
|
import net.corda.core.contracts.StateAndRef
|
||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.StateRef
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.crypto.DigitalSignature
|
import net.corda.core.crypto.DigitalSignature
|
||||||
import net.corda.core.flows.NotaryError
|
import net.corda.core.flows.NotaryError
|
||||||
import net.corda.core.flows.NotaryException
|
import net.corda.core.flows.NotaryException
|
||||||
@ -12,6 +11,7 @@ import net.corda.core.flows.NotaryFlow
|
|||||||
import net.corda.core.getOrThrow
|
import net.corda.core.getOrThrow
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.node.internal.AbstractNode
|
import net.corda.node.internal.AbstractNode
|
||||||
import net.corda.node.services.issueInvalidState
|
import net.corda.node.services.issueInvalidState
|
||||||
import net.corda.node.services.network.NetworkMapService
|
import net.corda.node.services.network.NetworkMapService
|
||||||
@ -52,7 +52,7 @@ class ValidatingNotaryServiceTests {
|
|||||||
fun `should report error for invalid transaction dependency`() {
|
fun `should report error for invalid transaction dependency`() {
|
||||||
val stx = run {
|
val stx = run {
|
||||||
val inputState = issueInvalidState(clientNode, notaryNode.info.notaryIdentity)
|
val inputState = issueInvalidState(clientNode, notaryNode.info.notaryIdentity)
|
||||||
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
|
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState)
|
||||||
clientNode.services.signInitialTransaction(tx)
|
clientNode.services.signInitialTransaction(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ class ValidatingNotaryServiceTests {
|
|||||||
val inputState = issueState(clientNode)
|
val inputState = issueState(clientNode)
|
||||||
|
|
||||||
val command = Command(DummyContract.Commands.Move(), expectedMissingKey)
|
val command = Command(DummyContract.Commands.Move(), expectedMissingKey)
|
||||||
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState, command)
|
val tx = TransactionBuilder(notaryNode.info.notaryIdentity).withItems(inputState, command)
|
||||||
clientNode.services.signInitialTransaction(tx)
|
clientNode.services.signInitialTransaction(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +403,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
|
|||||||
val freshKey = services.legalIdentityKey
|
val freshKey = services.legalIdentityKey
|
||||||
|
|
||||||
// Issue a txn to Send us some Money
|
// Issue a txn to Send us some Money
|
||||||
val usefulBuilder = TransactionType.General.Builder(null).apply {
|
val usefulBuilder = TransactionBuilder(null).apply {
|
||||||
Cash().generateIssue(this, 100.DOLLARS `issued by` MEGA_CORP.ref(1), AnonymousParty(freshKey), DUMMY_NOTARY)
|
Cash().generateIssue(this, 100.DOLLARS `issued by` MEGA_CORP.ref(1), AnonymousParty(freshKey), DUMMY_NOTARY)
|
||||||
}
|
}
|
||||||
val usefulTX = megaCorpServices.signInitialTransaction(usefulBuilder)
|
val usefulTX = megaCorpServices.signInitialTransaction(usefulBuilder)
|
||||||
@ -416,7 +416,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
|
|||||||
assertEquals(3, vaultSvc.getTransactionNotes(usefulTX.id).count())
|
assertEquals(3, vaultSvc.getTransactionNotes(usefulTX.id).count())
|
||||||
|
|
||||||
// Issue more Money (GBP)
|
// Issue more Money (GBP)
|
||||||
val anotherBuilder = TransactionType.General.Builder(null).apply {
|
val anotherBuilder = TransactionBuilder(null).apply {
|
||||||
Cash().generateIssue(this, 200.POUNDS `issued by` MEGA_CORP.ref(1), AnonymousParty(freshKey), DUMMY_NOTARY)
|
Cash().generateIssue(this, 200.POUNDS `issued by` MEGA_CORP.ref(1), AnonymousParty(freshKey), DUMMY_NOTARY)
|
||||||
}
|
}
|
||||||
val anotherTX = megaCorpServices.signInitialTransaction(anotherBuilder)
|
val anotherTX = megaCorpServices.signInitialTransaction(anotherBuilder)
|
||||||
|
@ -10,6 +10,7 @@ import net.corda.core.node.services.VaultService
|
|||||||
import net.corda.core.node.services.consumedStates
|
import net.corda.core.node.services.consumedStates
|
||||||
import net.corda.core.node.services.unconsumedStates
|
import net.corda.core.node.services.unconsumedStates
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.node.services.database.HibernateConfiguration
|
import net.corda.node.services.database.HibernateConfiguration
|
||||||
import net.corda.node.services.schema.NodeSchemaService
|
import net.corda.node.services.schema.NodeSchemaService
|
||||||
import net.corda.node.utilities.CordaPersistence
|
import net.corda.node.utilities.CordaPersistence
|
||||||
@ -93,7 +94,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
|||||||
database.transaction {
|
database.transaction {
|
||||||
// A tx that sends us money.
|
// A tx that sends us money.
|
||||||
val freshKey = services.keyManagementService.freshKey()
|
val freshKey = services.keyManagementService.freshKey()
|
||||||
val usefulBuilder = TransactionType.General.Builder(null)
|
val usefulBuilder = TransactionBuilder(null)
|
||||||
Cash().generateIssue(usefulBuilder, 100.DOLLARS `issued by` MEGA_CORP.ref(1), AnonymousParty(freshKey), DUMMY_NOTARY)
|
Cash().generateIssue(usefulBuilder, 100.DOLLARS `issued by` MEGA_CORP.ref(1), AnonymousParty(freshKey), DUMMY_NOTARY)
|
||||||
val usefulTX = megaCorpServices.signInitialTransaction(usefulBuilder)
|
val usefulTX = megaCorpServices.signInitialTransaction(usefulBuilder)
|
||||||
|
|
||||||
@ -101,7 +102,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
|||||||
services.recordTransactions(usefulTX)
|
services.recordTransactions(usefulTX)
|
||||||
|
|
||||||
// A tx that spends our money.
|
// A tx that spends our money.
|
||||||
val spendTXBuilder = TransactionType.General.Builder(DUMMY_NOTARY)
|
val spendTXBuilder = TransactionBuilder(DUMMY_NOTARY)
|
||||||
vault.generateSpend(spendTXBuilder, 80.DOLLARS, BOB)
|
vault.generateSpend(spendTXBuilder, 80.DOLLARS, BOB)
|
||||||
val spendPTX = services.signInitialTransaction(spendTXBuilder, freshKey)
|
val spendPTX = services.signInitialTransaction(spendTXBuilder, freshKey)
|
||||||
val spendTX = notaryServices.addSignature(spendPTX)
|
val spendTX = notaryServices.addSignature(spendPTX)
|
||||||
@ -109,7 +110,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
|||||||
assertEquals(100.DOLLARS, services.getCashBalance(USD))
|
assertEquals(100.DOLLARS, services.getCashBalance(USD))
|
||||||
|
|
||||||
// A tx that doesn't send us anything.
|
// A tx that doesn't send us anything.
|
||||||
val irrelevantBuilder = TransactionType.General.Builder(DUMMY_NOTARY)
|
val irrelevantBuilder = TransactionBuilder(DUMMY_NOTARY)
|
||||||
Cash().generateIssue(irrelevantBuilder, 100.DOLLARS `issued by` MEGA_CORP.ref(1), BOB, DUMMY_NOTARY)
|
Cash().generateIssue(irrelevantBuilder, 100.DOLLARS `issued by` MEGA_CORP.ref(1), BOB, DUMMY_NOTARY)
|
||||||
|
|
||||||
val irrelevantPTX = megaCorpServices.signInitialTransaction(irrelevantBuilder)
|
val irrelevantPTX = megaCorpServices.signInitialTransaction(irrelevantBuilder)
|
||||||
@ -147,7 +148,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
|||||||
backgroundExecutor.submit {
|
backgroundExecutor.submit {
|
||||||
database.transaction {
|
database.transaction {
|
||||||
try {
|
try {
|
||||||
val txn1Builder = TransactionType.General.Builder(DUMMY_NOTARY)
|
val txn1Builder = TransactionBuilder(DUMMY_NOTARY)
|
||||||
vault.generateSpend(txn1Builder, 60.DOLLARS, BOB)
|
vault.generateSpend(txn1Builder, 60.DOLLARS, BOB)
|
||||||
val ptxn1 = notaryServices.signInitialTransaction(txn1Builder)
|
val ptxn1 = notaryServices.signInitialTransaction(txn1Builder)
|
||||||
val txn1 = services.addSignature(ptxn1, freshKey)
|
val txn1 = services.addSignature(ptxn1, freshKey)
|
||||||
@ -177,7 +178,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
|||||||
backgroundExecutor.submit {
|
backgroundExecutor.submit {
|
||||||
database.transaction {
|
database.transaction {
|
||||||
try {
|
try {
|
||||||
val txn2Builder = TransactionType.General.Builder(DUMMY_NOTARY)
|
val txn2Builder = TransactionBuilder(DUMMY_NOTARY)
|
||||||
vault.generateSpend(txn2Builder, 80.DOLLARS, BOB)
|
vault.generateSpend(txn2Builder, 80.DOLLARS, BOB)
|
||||||
val ptxn2 = notaryServices.signInitialTransaction(txn2Builder)
|
val ptxn2 = notaryServices.signInitialTransaction(txn2Builder)
|
||||||
val txn2 = services.addSignature(ptxn2, freshKey)
|
val txn2 = services.addSignature(ptxn2, freshKey)
|
||||||
@ -219,7 +220,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
|||||||
val linearId = UniqueIdentifier()
|
val linearId = UniqueIdentifier()
|
||||||
|
|
||||||
// Issue a linear state
|
// Issue a linear state
|
||||||
val dummyIssueBuilder = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
|
val dummyIssueBuilder = TransactionBuilder(notary = DUMMY_NOTARY).apply {
|
||||||
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)))
|
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)))
|
||||||
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)))
|
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)))
|
||||||
}
|
}
|
||||||
@ -240,7 +241,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
|||||||
val linearId = UniqueIdentifier()
|
val linearId = UniqueIdentifier()
|
||||||
|
|
||||||
// Issue a linear state
|
// Issue a linear state
|
||||||
val dummyIssueBuilder = TransactionType.General.Builder(notary = DUMMY_NOTARY)
|
val dummyIssueBuilder = TransactionBuilder(notary = DUMMY_NOTARY)
|
||||||
dummyIssueBuilder.addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)))
|
dummyIssueBuilder.addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)))
|
||||||
val dummyIssuePtx = notaryServices.signInitialTransaction(dummyIssueBuilder)
|
val dummyIssuePtx = notaryServices.signInitialTransaction(dummyIssueBuilder)
|
||||||
val dummyIssue = services.addSignature(dummyIssuePtx)
|
val dummyIssue = services.addSignature(dummyIssuePtx)
|
||||||
@ -251,7 +252,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
|||||||
assertThat(vault.unconsumedStates<DummyLinearContract.State>()).hasSize(1)
|
assertThat(vault.unconsumedStates<DummyLinearContract.State>()).hasSize(1)
|
||||||
|
|
||||||
// Move the same state
|
// Move the same state
|
||||||
val dummyMoveBuilder = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
|
val dummyMoveBuilder = TransactionBuilder(notary = DUMMY_NOTARY).apply {
|
||||||
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)))
|
addOutputState(DummyLinearContract.State(linearId = linearId, participants = listOf(freshIdentity)))
|
||||||
addInputState(dummyIssue.tx.outRef<LinearState>(0))
|
addInputState(dummyIssue.tx.outRef<LinearState>(0))
|
||||||
}
|
}
|
||||||
@ -283,7 +284,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
|||||||
|
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// A tx that spends our money.
|
// A tx that spends our money.
|
||||||
val spendTXBuilder = TransactionType.General.Builder(DUMMY_NOTARY)
|
val spendTXBuilder = TransactionBuilder(DUMMY_NOTARY)
|
||||||
vault.generateSpend(spendTXBuilder, 80.DOLLARS, BOB)
|
vault.generateSpend(spendTXBuilder, 80.DOLLARS, BOB)
|
||||||
val spendPTX = notaryServices.signInitialTransaction(spendTXBuilder)
|
val spendPTX = notaryServices.signInitialTransaction(spendTXBuilder)
|
||||||
val spendTX = services.addSignature(spendPTX, freshKey)
|
val spendTX = services.addSignature(spendPTX, freshKey)
|
||||||
@ -313,7 +314,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
|
|||||||
linearStates.forEach { println(it.state.data.linearId) }
|
linearStates.forEach { println(it.state.data.linearId) }
|
||||||
|
|
||||||
// Create a txn consuming different contract types
|
// Create a txn consuming different contract types
|
||||||
val dummyMoveBuilder = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
|
val dummyMoveBuilder = TransactionBuilder(notary = DUMMY_NOTARY).apply {
|
||||||
addOutputState(DummyLinearContract.State(participants = listOf(freshIdentity)))
|
addOutputState(DummyLinearContract.State(participants = listOf(freshIdentity)))
|
||||||
addOutputState(DummyDealContract.State(ref = "999", participants = listOf(freshIdentity)))
|
addOutputState(DummyDealContract.State(ref = "999", participants = listOf(freshIdentity)))
|
||||||
addInputState(linearStates.first())
|
addInputState(linearStates.first())
|
||||||
|
@ -5,7 +5,6 @@ import joptsimple.OptionParser
|
|||||||
import net.corda.client.rpc.CordaRPCClient
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.core.contracts.Contract
|
import net.corda.core.contracts.Contract
|
||||||
import net.corda.core.contracts.ContractState
|
import net.corda.core.contracts.ContractState
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.flows.FinalityFlow
|
import net.corda.core.flows.FinalityFlow
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
@ -19,6 +18,7 @@ import net.corda.core.messaging.CordaRPCOps
|
|||||||
import net.corda.core.messaging.startTrackedFlow
|
import net.corda.core.messaging.startTrackedFlow
|
||||||
import net.corda.core.transactions.LedgerTransaction
|
import net.corda.core.transactions.LedgerTransaction
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.ProgressTracker
|
import net.corda.core.utilities.ProgressTracker
|
||||||
import net.corda.testing.DUMMY_BANK_B
|
import net.corda.testing.DUMMY_BANK_B
|
||||||
@ -106,7 +106,7 @@ class AttachmentDemoFlow(val otherSide: Party, val hash: SecureHash.SHA256) : Fl
|
|||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call(): SignedTransaction {
|
override fun call(): SignedTransaction {
|
||||||
// Create a trivial transaction with an output that describes the attachment, and the attachment itself
|
// Create a trivial transaction with an output that describes the attachment, and the attachment itself
|
||||||
val ptx = TransactionType.General.Builder(notary = DUMMY_NOTARY)
|
val ptx = TransactionBuilder(notary = DUMMY_NOTARY)
|
||||||
ptx.addOutputState(AttachmentContract.State(hash))
|
ptx.addOutputState(AttachmentContract.State(hash))
|
||||||
ptx.addAttachment(hash)
|
ptx.addAttachment(hash)
|
||||||
|
|
||||||
|
@ -783,7 +783,7 @@ class InterestRateSwap : Contract {
|
|||||||
|
|
||||||
// Put all the above into a new State object.
|
// Put all the above into a new State object.
|
||||||
val state = State(fixedLeg, floatingLeg, newCalculation, common)
|
val state = State(fixedLeg, floatingLeg, newCalculation, common)
|
||||||
return TransactionType.General.Builder(notary = notary).withItems(state, Command(Commands.Agree(), listOf(state.floatingLeg.floatingRatePayer.owningKey, state.fixedLeg.fixedRatePayer.owningKey)))
|
return TransactionBuilder(notary).withItems(state, Command(Commands.Agree(), listOf(state.floatingLeg.floatingRatePayer.owningKey, state.fixedLeg.fixedRatePayer.owningKey)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun calcFixingDate(date: LocalDate, fixingPeriodOffset: Int, calendar: BusinessCalendar): LocalDate {
|
private fun calcFixingDate(date: LocalDate, fixingPeriodOffset: Int, calendar: BusinessCalendar): LocalDate {
|
||||||
|
@ -61,7 +61,7 @@ object FixingFlow {
|
|||||||
|
|
||||||
val newDeal = deal
|
val newDeal = deal
|
||||||
|
|
||||||
val ptx = TransactionType.General.Builder(txState.notary)
|
val ptx = TransactionBuilder(txState.notary)
|
||||||
|
|
||||||
val oracle = serviceHub.networkMapCache.getNodesWithService(handshake.payload.oracleType).first()
|
val oracle = serviceHub.networkMapCache.getNodesWithService(handshake.payload.oracleType).first()
|
||||||
val oracleParty = oracle.serviceIdentities(handshake.payload.oracleType).first()
|
val oracleParty = oracle.serviceIdentities(handshake.payload.oracleType).first()
|
||||||
|
@ -208,7 +208,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
|
|||||||
n2.database.transaction {
|
n2.database.transaction {
|
||||||
n2.installCordaService(NodeInterestRates.Oracle::class.java).knownFixes = TEST_DATA
|
n2.installCordaService(NodeInterestRates.Oracle::class.java).knownFixes = TEST_DATA
|
||||||
}
|
}
|
||||||
val tx = TransactionType.General.Builder(null)
|
val tx = TransactionBuilder(null)
|
||||||
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
|
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
|
||||||
val oracle = n2.info.serviceIdentities(NodeInterestRates.Oracle.type).first()
|
val oracle = n2.info.serviceIdentities(NodeInterestRates.Oracle.type).first()
|
||||||
val flow = FilteredRatesFlow(tx, oracle, fixOf, BigDecimal("0.675"), BigDecimal("0.1"))
|
val flow = FilteredRatesFlow(tx, oracle, fixOf, BigDecimal("0.675"), BigDecimal("0.1"))
|
||||||
@ -239,6 +239,6 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makeTX() = TransactionType.General.Builder(DUMMY_NOTARY).withItems(
|
private fun makeTX() = TransactionBuilder(DUMMY_NOTARY).withItems(
|
||||||
1000.DOLLARS.CASH `issued by` DUMMY_CASH_ISSUER `owned by` ALICE `with notary` DUMMY_NOTARY)
|
1000.DOLLARS.CASH `issued by` DUMMY_CASH_ISSUER `owned by` ALICE `with notary` DUMMY_NOTARY)
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package net.corda.irs.contract
|
|||||||
import net.corda.contracts.*
|
import net.corda.contracts.*
|
||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.node.MockServices
|
import net.corda.testing.node.MockServices
|
||||||
@ -305,7 +306,7 @@ class IRSTests : TestDependencyInjectionBase() {
|
|||||||
while (true) {
|
while (true) {
|
||||||
val nextFix: FixOf = currentIRS().nextFixingOf() ?: break
|
val nextFix: FixOf = currentIRS().nextFixingOf() ?: break
|
||||||
val fixTX: SignedTransaction = run {
|
val fixTX: SignedTransaction = run {
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY)
|
val tx = TransactionBuilder(DUMMY_NOTARY)
|
||||||
val fixing = Fix(nextFix, "0.052".percent.value)
|
val fixing = Fix(nextFix, "0.052".percent.value)
|
||||||
InterestRateSwap().generateFix(tx, previousTXN.tx.outRef(0), fixing)
|
InterestRateSwap().generateFix(tx, previousTXN.tx.outRef(0), fixing)
|
||||||
tx.setTimeWindow(TEST_TX_TIME, 30.seconds)
|
tx.setTimeWindow(TEST_TX_TIME, 30.seconds)
|
||||||
|
@ -2,7 +2,6 @@ package net.corda.vega.contracts
|
|||||||
|
|
||||||
import net.corda.contracts.DealState
|
import net.corda.contracts.DealState
|
||||||
import net.corda.core.contracts.Command
|
import net.corda.core.contracts.Command
|
||||||
import net.corda.core.contracts.TransactionType
|
|
||||||
import net.corda.core.contracts.UniqueIdentifier
|
import net.corda.core.contracts.UniqueIdentifier
|
||||||
import net.corda.core.crypto.keys
|
import net.corda.core.crypto.keys
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
@ -29,6 +28,6 @@ data class IRSState(val swap: SwapData,
|
|||||||
|
|
||||||
override fun generateAgreement(notary: Party): TransactionBuilder {
|
override fun generateAgreement(notary: Party): TransactionBuilder {
|
||||||
val state = IRSState(swap, buyer, seller, OGTrade())
|
val state = IRSState(swap, buyer, seller, OGTrade())
|
||||||
return TransactionType.General.Builder(notary).withItems(state, Command(OGTrade.Commands.Agree(), participants.map { it.owningKey }))
|
return TransactionBuilder(notary).withItems(state, Command(OGTrade.Commands.Agree(), participants.map { it.owningKey }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ data class PortfolioState(val portfolio: List<StateRef>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun generateAgreement(notary: Party): TransactionBuilder {
|
override fun generateAgreement(notary: Party): TransactionBuilder {
|
||||||
return TransactionType.General.Builder(notary).withItems(copy(), Command(PortfolioSwap.Commands.Agree(), participants.map { it.owningKey }))
|
return TransactionBuilder(notary).withItems(copy(), Command(PortfolioSwap.Commands.Agree(), participants.map { it.owningKey }))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateRevision(notary: Party, oldState: StateAndRef<*>, updatedValue: Update): TransactionBuilder {
|
override fun generateRevision(notary: Party, oldState: StateAndRef<*>, updatedValue: Update): TransactionBuilder {
|
||||||
@ -50,7 +50,7 @@ data class PortfolioState(val portfolio: List<StateRef>,
|
|||||||
val portfolio = updatedValue.portfolio ?: portfolio
|
val portfolio = updatedValue.portfolio ?: portfolio
|
||||||
val valuation = updatedValue.valuation ?: valuation
|
val valuation = updatedValue.valuation ?: valuation
|
||||||
|
|
||||||
val tx = TransactionType.General.Builder(notary)
|
val tx = TransactionBuilder(notary)
|
||||||
tx.addInputState(oldState)
|
tx.addInputState(oldState)
|
||||||
tx.addOutputState(copy(portfolio = portfolio, valuation = valuation))
|
tx.addOutputState(copy(portfolio = portfolio, valuation = valuation))
|
||||||
tx.addCommand(PortfolioSwap.Commands.Update(), participants.map { it.owningKey })
|
tx.addCommand(PortfolioSwap.Commands.Update(), participants.map { it.owningKey })
|
||||||
|
@ -16,6 +16,7 @@ import net.corda.core.identity.Party
|
|||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.ProgressTracker
|
import net.corda.core.utilities.ProgressTracker
|
||||||
import net.corda.flows.TwoPartyTradeFlow
|
import net.corda.flows.TwoPartyTradeFlow
|
||||||
import net.corda.testing.BOC
|
import net.corda.testing.BOC
|
||||||
@ -91,7 +92,7 @@ class SellerFlow(val otherParty: Party,
|
|||||||
|
|
||||||
// Now make a dummy transaction that moves it to a new key, just to show that resolving dependencies works.
|
// Now make a dummy transaction that moves it to a new key, just to show that resolving dependencies works.
|
||||||
val move: SignedTransaction = run {
|
val move: SignedTransaction = run {
|
||||||
val builder = TransactionType.General.Builder(notaryNode.notaryIdentity)
|
val builder = TransactionBuilder(notaryNode.notaryIdentity)
|
||||||
CommercialPaper().generateMove(builder, issuance.tx.outRef(0), ownedBy)
|
CommercialPaper().generateMove(builder, issuance.tx.outRef(0), ownedBy)
|
||||||
val stx = serviceHub.signInitialTransaction(builder)
|
val stx = serviceHub.signInitialTransaction(builder)
|
||||||
subFlow(FinalityFlow(stx)).single()
|
subFlow(FinalityFlow(stx)).single()
|
||||||
|
@ -50,10 +50,10 @@ data class DummyContract(override val legalContractReference: SecureHash = Secur
|
|||||||
val owners = listOf(owner) + otherOwners
|
val owners = listOf(owner) + otherOwners
|
||||||
return if (owners.size == 1) {
|
return if (owners.size == 1) {
|
||||||
val state = SingleOwnerState(magicNumber, owners.first().party)
|
val state = SingleOwnerState(magicNumber, owners.first().party)
|
||||||
TransactionType.General.Builder(notary = notary).withItems(state, Command(Commands.Create(), owners.first().party.owningKey))
|
TransactionBuilder(notary).withItems(state, Command(Commands.Create(), owners.first().party.owningKey))
|
||||||
} else {
|
} else {
|
||||||
val state = MultiOwnerState(magicNumber, owners.map { it.party })
|
val state = MultiOwnerState(magicNumber, owners.map { it.party })
|
||||||
TransactionType.General.Builder(notary = notary).withItems(state, Command(Commands.Create(), owners.map { it.party.owningKey }))
|
TransactionBuilder(notary).withItems(state, Command(Commands.Create(), owners.map { it.party.owningKey }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ data class DummyContract(override val legalContractReference: SecureHash = Secur
|
|||||||
require(priors.isNotEmpty())
|
require(priors.isNotEmpty())
|
||||||
val priorState = priors[0].state.data
|
val priorState = priors[0].state.data
|
||||||
val (cmd, state) = priorState.withNewOwner(newOwner)
|
val (cmd, state) = priorState.withNewOwner(newOwner)
|
||||||
return TransactionType.General.Builder(notary = priors[0].state.notary).withItems(
|
return TransactionBuilder(notary = priors[0].state.notary).withItems(
|
||||||
/* INPUTS */ *priors.toTypedArray(),
|
/* INPUTS */ *priors.toTypedArray(),
|
||||||
/* COMMAND */ Command(cmd, priorState.owner.owningKey),
|
/* COMMAND */ Command(cmd, priorState.owner.owningKey),
|
||||||
/* OUTPUT */ state
|
/* OUTPUT */ state
|
||||||
|
@ -5,6 +5,7 @@ import net.corda.core.crypto.SecureHash
|
|||||||
import net.corda.core.flows.ContractUpgradeFlow
|
import net.corda.core.flows.ContractUpgradeFlow
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.transactions.LedgerTransaction
|
import net.corda.core.transactions.LedgerTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.transactions.WireTransaction
|
import net.corda.core.transactions.WireTransaction
|
||||||
|
|
||||||
// The dummy contract doesn't do anything useful. It exists for testing purposes.
|
// The dummy contract doesn't do anything useful. It exists for testing purposes.
|
||||||
@ -51,7 +52,7 @@ class DummyContractV2 : UpgradedContract<DummyContract.State, DummyContractV2.St
|
|||||||
require(states.isNotEmpty())
|
require(states.isNotEmpty())
|
||||||
|
|
||||||
val signees: Set<AbstractParty> = states.flatMap { it.state.data.participants }.distinct().toSet()
|
val signees: Set<AbstractParty> = states.flatMap { it.state.data.participants }.distinct().toSet()
|
||||||
return Pair(TransactionType.General.Builder(notary).apply {
|
return Pair(TransactionBuilder(notary).apply {
|
||||||
states.forEach {
|
states.forEach {
|
||||||
addInputState(it)
|
addInputState(it)
|
||||||
addOutputState(upgrade(it.state.data))
|
addOutputState(upgrade(it.state.data))
|
||||||
|
@ -13,6 +13,7 @@ import net.corda.core.node.ServiceHub
|
|||||||
import net.corda.core.node.services.Vault
|
import net.corda.core.node.services.Vault
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.testing.CHARLIE
|
import net.corda.testing.CHARLIE
|
||||||
import net.corda.testing.DUMMY_NOTARY
|
import net.corda.testing.DUMMY_NOTARY
|
||||||
import net.corda.testing.DUMMY_NOTARY_KEY
|
import net.corda.testing.DUMMY_NOTARY_KEY
|
||||||
@ -30,7 +31,7 @@ fun ServiceHub.fillWithSomeTestDeals(dealIds: List<String>,
|
|||||||
|
|
||||||
val transactions: List<SignedTransaction> = dealIds.map {
|
val transactions: List<SignedTransaction> = dealIds.map {
|
||||||
// Issue a deal state
|
// Issue a deal state
|
||||||
val dummyIssue = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
|
val dummyIssue = TransactionBuilder(notary = DUMMY_NOTARY).apply {
|
||||||
addOutputState(DummyDealContract.State(ref = it, participants = participants.plus(me)))
|
addOutputState(DummyDealContract.State(ref = it, participants = participants.plus(me)))
|
||||||
signWith(DUMMY_NOTARY_KEY)
|
signWith(DUMMY_NOTARY_KEY)
|
||||||
}
|
}
|
||||||
@ -60,7 +61,7 @@ fun ServiceHub.fillWithSomeTestLinearStates(numberToCreate: Int,
|
|||||||
|
|
||||||
val transactions: List<SignedTransaction> = (1..numberToCreate).map {
|
val transactions: List<SignedTransaction> = (1..numberToCreate).map {
|
||||||
// Issue a Linear state
|
// Issue a Linear state
|
||||||
val dummyIssue = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
|
val dummyIssue = TransactionBuilder(notary = DUMMY_NOTARY).apply {
|
||||||
addOutputState(DummyLinearContract.State(
|
addOutputState(DummyLinearContract.State(
|
||||||
linearId = UniqueIdentifier(externalId),
|
linearId = UniqueIdentifier(externalId),
|
||||||
participants = participants.plus(me),
|
participants = participants.plus(me),
|
||||||
@ -111,7 +112,7 @@ fun ServiceHub.fillWithSomeTestCash(howMuch: Amount<Currency>,
|
|||||||
// We will allocate one state to one transaction, for simplicities sake.
|
// We will allocate one state to one transaction, for simplicities sake.
|
||||||
val cash = Cash()
|
val cash = Cash()
|
||||||
val transactions: List<SignedTransaction> = amounts.map { pennies ->
|
val transactions: List<SignedTransaction> = amounts.map { pennies ->
|
||||||
val issuance = TransactionType.General.Builder(null as Party?)
|
val issuance = TransactionBuilder(null as Party?)
|
||||||
cash.generateIssue(issuance, Amount(pennies, Issued(issuedBy.copy(reference = ref), howMuch.token)), me, outputNotary)
|
cash.generateIssue(issuance, Amount(pennies, Issued(issuedBy.copy(reference = ref), howMuch.token)), me, outputNotary)
|
||||||
issuance.signWith(issuerKey)
|
issuance.signWith(issuerKey)
|
||||||
|
|
||||||
@ -139,7 +140,7 @@ fun ServiceHub.fillWithSomeTestCommodity(amount: Amount<Commodity>,
|
|||||||
val me = AnonymousParty(myKey)
|
val me = AnonymousParty(myKey)
|
||||||
|
|
||||||
val commodity = CommodityContract()
|
val commodity = CommodityContract()
|
||||||
val issuance = TransactionType.General.Builder(null as Party?)
|
val issuance = TransactionBuilder(null as Party?)
|
||||||
commodity.generateIssue(issuance, Amount(amount.quantity, Issued(issuedBy.copy(reference = ref), amount.token)), me, outputNotary)
|
commodity.generateIssue(issuance, Amount(amount.quantity, Issued(issuedBy.copy(reference = ref), amount.token)), me, outputNotary)
|
||||||
issuance.signWith(issuerKey)
|
issuance.signWith(issuerKey)
|
||||||
val transaction = issuance.toSignedTransaction(true)
|
val transaction = issuance.toSignedTransaction(true)
|
||||||
@ -180,7 +181,7 @@ fun calculateRandomlySizedAmounts(howMuch: Amount<Currency>, min: Int, max: Int,
|
|||||||
fun <T : LinearState> ServiceHub.consume(states: List<StateAndRef<T>>) {
|
fun <T : LinearState> ServiceHub.consume(states: List<StateAndRef<T>>) {
|
||||||
// Create a txn consuming different contract types
|
// Create a txn consuming different contract types
|
||||||
states.forEach {
|
states.forEach {
|
||||||
val consumedTx = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
|
val consumedTx = TransactionBuilder(notary = DUMMY_NOTARY).apply {
|
||||||
addInputState(it)
|
addInputState(it)
|
||||||
signWith(DUMMY_NOTARY_KEY)
|
signWith(DUMMY_NOTARY_KEY)
|
||||||
}.toSignedTransaction()
|
}.toSignedTransaction()
|
||||||
@ -191,7 +192,7 @@ fun <T : LinearState> ServiceHub.consume(states: List<StateAndRef<T>>) {
|
|||||||
|
|
||||||
fun <T : LinearState> ServiceHub.consumeAndProduce(stateAndRef: StateAndRef<T>): StateAndRef<T> {
|
fun <T : LinearState> ServiceHub.consumeAndProduce(stateAndRef: StateAndRef<T>): StateAndRef<T> {
|
||||||
// Create a txn consuming different contract types
|
// Create a txn consuming different contract types
|
||||||
val consumedTx = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
|
val consumedTx = TransactionBuilder(notary = DUMMY_NOTARY).apply {
|
||||||
addInputState(stateAndRef)
|
addInputState(stateAndRef)
|
||||||
signWith(DUMMY_NOTARY_KEY)
|
signWith(DUMMY_NOTARY_KEY)
|
||||||
}.toSignedTransaction()
|
}.toSignedTransaction()
|
||||||
@ -199,7 +200,7 @@ fun <T : LinearState> ServiceHub.consumeAndProduce(stateAndRef: StateAndRef<T>):
|
|||||||
recordTransactions(consumedTx)
|
recordTransactions(consumedTx)
|
||||||
|
|
||||||
// Create a txn consuming different contract types
|
// Create a txn consuming different contract types
|
||||||
val producedTx = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
|
val producedTx = TransactionBuilder(notary = DUMMY_NOTARY).apply {
|
||||||
addOutputState(DummyLinearContract.State(linearId = stateAndRef.state.data.linearId,
|
addOutputState(DummyLinearContract.State(linearId = stateAndRef.state.data.linearId,
|
||||||
participants = stateAndRef.state.data.participants))
|
participants = stateAndRef.state.data.participants))
|
||||||
signWith(DUMMY_NOTARY_KEY)
|
signWith(DUMMY_NOTARY_KEY)
|
||||||
@ -224,7 +225,7 @@ fun ServiceHub.evolveLinearState(linearState: StateAndRef<LinearState>) : StateA
|
|||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun ServiceHub.consumeCash(amount: Amount<Currency>, to: Party = CHARLIE): Vault<Cash.State> {
|
fun ServiceHub.consumeCash(amount: Amount<Currency>, to: Party = CHARLIE): Vault<Cash.State> {
|
||||||
// A tx that spends our money.
|
// A tx that spends our money.
|
||||||
val spendTX = TransactionType.General.Builder(DUMMY_NOTARY).apply {
|
val spendTX = TransactionBuilder(DUMMY_NOTARY).apply {
|
||||||
vaultService.generateSpend(this, amount, to)
|
vaultService.generateSpend(this, amount, to)
|
||||||
signWith(DUMMY_NOTARY_KEY)
|
signWith(DUMMY_NOTARY_KEY)
|
||||||
}.toSignedTransaction(checkSufficientSignatures = false)
|
}.toSignedTransaction(checkSufficientSignatures = false)
|
||||||
|
Loading…
Reference in New Issue
Block a user