2017-01-06 11:05:37 +00:00
Building transactions
2016-11-28 13:39:34 +00:00
=====================
Introduction
------------
2017-07-27 12:14:08 +00:00
Understanding and implementing transactions in Corda is key to building
and implementing real world smart contracts. It is only through
construction of valid Corda transactions containing appropriate data
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
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,
or to prevent malicious activity. This document details some of the
considerations and APIs used to when constructing transactions as part
of a flow.
2016-11-28 13:39:34 +00:00
The Basic Lifecycle Of Transactions
-----------------------------------
2017-10-01 22:33:15 +00:00
Transactions in Corda contain a number of elements:
2017-07-27 12:14:08 +00:00
1. A set of Input state references that will be consumed by the final
2017-10-01 22:33:15 +00:00
accepted transaction
2017-07-27 12:14:08 +00:00
2. A set of Output states to create/replace the consumed states and thus
2017-10-01 22:33:15 +00:00
become the new latest versions of data on the ledger
2017-07-27 12:14:08 +00:00
3. A set of `` Attachment `` items which can contain legal documents, contract
2017-10-01 22:33:15 +00:00
code, or private encrypted sections as an extension beyond the native
contract states
4. A set of `` Command `` items which indicate the type of ledger
transition that is encoded in the transaction. Each command also has an
associated set of signer keys, which will be required to sign the
transaction
5. A signers list, which is the union of the signers on the individual
Command objects
6. A notary identity to specify which notary node is tracking the
state consumption (if the transaction's input states are registered with different
notary nodes the flow will have to insert additional `` NotaryChange ``
transactions to migrate the states across to a consistent notary node
before being allowed to mutate any states)
2018-05-24 15:06:33 +00:00
7. Optionally a time-window that can used by the notary to bound the
2017-10-01 22:33:15 +00:00
period during which the proposed transaction can be committed to the
ledger
2019-02-20 17:05:36 +00:00
A transaction is built by populating a `` TransactionBuilder `` . Once the builder is fully populated, the flow should freeze the `` TransactionBuilder `` by signing it to create a `` SignedTransaction `` . This is key to the ledger agreement process - once a flow has attached a node’ s signature to a transaction, it has effectively stated that it accepts all the details of the transaction.
2017-10-01 22:33:15 +00:00
It is best practice for flows to receive back the `` TransactionSignature `` of other parties rather than a full
`` SignedTransaction `` objects, because otherwise we have to separately check that this is still the same
2017-07-27 12:14:08 +00:00
`` SignedTransaction `` and not a malicious substitute.
2017-10-01 22:33:15 +00:00
The final stage of committing the transaction to the ledger is to notarise the `` SignedTransaction `` , distribute it to
all appropriate parties and record the data into the ledger. These actions are best delegated to the `` FinalityFlow `` ,
rather than calling the individual steps manually. However, do note that the final broadcast to the other nodes is
asynchronous, so care must be used in unit testing to correctly await the vault updates.
2016-11-28 13:39:34 +00:00
Gathering Inputs
----------------
2017-07-27 12:14:08 +00:00
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
of the business process being captured by the smart contract and the
parameterised details of the request. However, it will generally involve
2017-10-01 22:33:15 +00:00
searching the vault via the `` VaultService `` interface on the
2016-11-28 13:39:34 +00:00
`` ServiceHub `` to locate the input states.
2017-07-27 12:14:08 +00:00
To give a few more specific details consider two simplified real world
2017-10-01 22:33:15 +00:00
scenarios. First, a basic foreign exchange cash transaction. This
2017-07-27 12:14:08 +00:00
transaction needs to locate a set of funds to exchange. A flow
2018-02-01 18:34:44 +00:00
modelling this is implemented in `` FxTransactionBuildTutorial.kt ``
2018-11-14 14:16:22 +00:00
(in the `main Corda repo <https://github.com/corda/corda> `_ ).
2017-10-01 22:33:15 +00:00
Second, a simple business model in which parties manually accept or
reject each other's trade proposals, which is implemented in
2018-11-14 14:16:22 +00:00
`` WorkflowTransactionBuildTutorial.kt `` (in the
2018-02-01 18:34:44 +00:00
`main Corda repo <https://github.com/corda/corda> `_ ). To run and explore these
2017-10-01 22:33:15 +00:00
examples using the IntelliJ IDE one can run/step through the respective unit
2017-07-27 12:14:08 +00:00
tests in `` FxTransactionBuildTutorialTest.kt `` and
`` WorkflowTransactionBuildTutorialTest.kt `` , which drive the flows as
2017-04-27 09:30:16 +00:00
part of a simulated in-memory network of nodes.
.. note :: Before creating the IntelliJ run configurations for these unit tests
2018-05-09 14:19:35 +00:00
go to Run -> Edit Configurations -> Defaults -> JUnit, add
2017-10-01 22:33:15 +00:00
`` -javaagent:lib/quasar.jar ``
2017-04-27 09:30:16 +00:00
to the VM options, and set Working directory to `` $PROJECT_DIR$ ``
so that the `` Quasar `` instrumentation is correctly configured.
2016-11-28 13:39:34 +00:00
2017-10-01 22:33:15 +00:00
For the cash transaction, let’ s assume we are using the
standard `` CashState `` in the `` :financial `` Gradle module. The `` Cash ``
2017-08-03 10:47:15 +00:00
contract uses `` FungibleAsset `` states to model holdings of
2017-10-01 22:33:15 +00:00
interchangeable assets and allow the splitting, merging and summing of
2017-08-03 10:47:15 +00:00
states to meet a contractual obligation. We would normally use the
2017-08-03 16:17:17 +00:00
`` Cash.generateSpend `` method to gather the required
2017-10-01 22:33:15 +00:00
amount of cash into a `` TransactionBuilder `` , set the outputs and generate the `` Move ``
command. However, to make things clearer, the example flow code shown
here will manually carry out the input queries by specifying relevant
2017-08-03 16:17:17 +00:00
query criteria filters to the `` tryLockFungibleStatesForSpending `` method
of the `` VaultService `` .
2016-11-28 13:39:34 +00:00
2018-09-24 14:00:31 +00:00
.. literalinclude :: example-code/src/main/kotlin/net/corda/docs/kotlin/FxTransactionBuildTutorial.kt
2016-11-28 13:39:34 +00:00
:language: kotlin
:start-after: DOCSTART 1
:end-before: DOCEND 1
2017-10-01 22:33:15 +00:00
This is a foreign exchange transaction, so we expect another set of input states of another currency from a
counterparty. However, the Corda privacy model means we are not aware of the other node’ s states. Our flow must
therefore ask the other node to carry out a similar query and return the additional inputs to the transaction (see the
`` ForeignExchangeFlow `` for more details of the exchange). We now have all the required input `` StateRef `` items, and
can turn to gathering the outputs.
2017-07-27 12:14:08 +00:00
For the trade approval flow we need to implement a simple workflow
pattern. We start by recording the unconfirmed trade details in a state
object implementing the `` LinearState `` interface. One field of this
record is used to map the business workflow to an enumerated state.
Initially the initiator creates a new state object which receives a new
`` UniqueIdentifier `` in its `` linearId `` property and a starting
workflow state of `` NEW `` . The `` Contract.verify `` method is written to
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
both ledgers for audit purposes, but the state is prevented from being
maliciously put in an approved state. The subsequent workflow steps then
follow with transactions that consume the state as inputs on one side
and output a new version with whatever state updates, or amendments
match to the business process, the `` linearId `` being preserved across
the changes. Attached `` Command `` objects help the verify method
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
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
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
initiate the relevant flow using `` StateRef `` , or `` linearId `` values as
2016-11-28 13:39:34 +00:00
parameters to the flow to identify the states being operated upon. Thus
2017-08-03 10:47:15 +00:00
code to gather the latest input state for a given `` StateRef `` would use
2017-09-27 12:33:23 +00:00
the `` VaultService `` as follows:
2016-11-28 13:39:34 +00:00
2018-11-14 14:16:22 +00:00
.. literalinclude :: example-code/src/main/kotlin/net/corda/docs/kotlin/txbuild/WorkflowTransactionBuildTutorial.kt
2016-11-28 13:39:34 +00:00
:language: kotlin
:start-after: DOCSTART 1
:end-before: DOCEND 1
2017-10-01 22:33:15 +00:00
:dedent: 8
2016-11-28 13:39:34 +00:00
Generating Commands
-------------------
2017-07-27 12:14:08 +00:00
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
the `` Contract.verify `` method the command will be used to select the
validation code path. The `` Contract.verify `` method will then restrict
the allowed contents of the transaction to reflect this context. Typical
restrictions might include that the input cash amount must equal the
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 foreign exchange rate, or the identity of one party, or the StateRef
of the specific input that originates the command in a bulk operation.
This data will be used to further aid the `` Contract.verify `` , because
to ensure consistent, secure and reproducible behaviour in a distributed
environment the `` Contract.verify `` , transaction is the only allowed to
use the content of the transaction to decide validity.
Another essential requirement for commands is that the correct set of
2017-10-01 22:33:15 +00:00
`` PublicKey `` objects are added to the `` Command `` on the builder, which will be
2017-07-27 12:14:08 +00:00
used to form the set of required signers on the final validated
transaction. These must correctly align with the expectations of the
`` Contract.verify `` method, which should be written to defensively check
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
addition, other signatories will often be required e.g. an Oracle
identity for an Oracle command, or both parties when there is an
exchange of assets.
2016-11-28 13:39:34 +00:00
Generating Outputs
------------------
2017-10-01 22:33:15 +00:00
Having located a `` StateAndRefs `` set as the transaction inputs, the
2017-07-27 12:14:08 +00:00
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
transitioned in the transaction. The contract code may provide a
`` generateXXX `` method to help with this process if the task is more
complicated. With a workflow state a slightly modified copy state is
usually sufficient, especially as it is expected that we wish to preserve
the `` linearId `` between state revisions, so that Vault queries can find
2016-11-28 13:39:34 +00:00
the latest revision.
2017-10-01 22:33:15 +00:00
For fungible contract states such as `` cash `` it is common to distribute
2017-07-27 12:14:08 +00:00
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. Remember that the result of a successful transaction is always to
fully consume/spend the input states, so this is required to conserve
the total cash. For example from the demo code:
2016-11-28 13:39:34 +00:00
2018-09-24 14:00:31 +00:00
.. literalinclude :: example-code/src/main/kotlin/net/corda/docs/kotlin/FxTransactionBuildTutorial.kt
2016-11-28 13:39:34 +00:00
:language: kotlin
:start-after: DOCSTART 2
:end-before: DOCEND 2
2017-10-01 22:33:15 +00:00
:dedent: 4
Building the SignedTransaction
------------------------------
Having gathered all the components for the transaction we now need to use a `` TransactionBuilder `` to construct the
full `` SignedTransaction `` . We instantiate a `` TransactionBuilder `` and provide a notary that will be associated with
the output states. Then we keep adding inputs, outputs, commands and attachments to complete the transaction.
2016-11-28 13:39:34 +00:00
2017-10-01 22:33:15 +00:00
Once the transaction is fully formed, we call `` ServiceHub.signInitialTransaction `` to sign the `` TransactionBuilder ``
and convert it into a `` SignedTransaction `` .
2016-11-28 13:39:34 +00:00
2017-10-01 22:33:15 +00:00
Examples of this process are:
2016-11-28 13:39:34 +00:00
2018-11-14 14:16:22 +00:00
.. literalinclude :: example-code/src/main/kotlin/net/corda/docs/kotlin/txbuild/WorkflowTransactionBuildTutorial.kt
2016-11-28 13:39:34 +00:00
:language: kotlin
:start-after: DOCSTART 2
:end-before: DOCEND 2
2017-10-01 22:33:15 +00:00
:dedent: 8
2016-11-28 13:39:34 +00:00
2018-09-24 14:00:31 +00:00
.. literalinclude :: example-code/src/main/kotlin/net/corda/docs/kotlin/FxTransactionBuildTutorial.kt
2016-11-28 13:39:34 +00:00
:language: kotlin
:start-after: DOCSTART 3
:end-before: DOCEND 3
2017-10-01 22:33:15 +00:00
:dedent: 4
2016-11-28 13:39:34 +00:00
Completing the SignedTransaction
--------------------------------
2017-10-01 22:33:15 +00:00
Having created an initial `` TransactionBuilder `` and converted this to a `` SignedTransaction `` , the process of
verifying and forming a full `` SignedTransaction `` begins and then completes with the
2017-07-27 12:14:08 +00:00
notarisation. In practice this is a relatively stereotypical process,
2017-10-01 22:33:15 +00:00
because assuming the `` SignedTransaction `` is correctly constructed the
2017-07-27 12:14:08 +00:00
verification should be immediate. However, it is also important to
recheck the business details of any data received back from an external
node, because a malicious party could always modify the contents before
returning the transaction. Each remote flow should therefore check as
much as possible of the initial `` SignedTransaction `` inside the `` unwrap `` of
the receive before agreeing to sign. Any issues should immediately throw
an exception to abort the flow. Similarly the originator, should always
apply any new signatures to its original proposal to ensure the contents
2016-11-28 13:39:34 +00:00
of the transaction has not been altered by the remote parties.
2017-07-27 12:14:08 +00:00
The typical code therefore checks the received `` SignedTransaction ``
2017-07-17 14:42:08 +00:00
using the `` verifySignaturesExcept `` method, excluding itself, the
2017-10-01 22:33:15 +00:00
notary and any other parties yet to apply their signature. The contents of the `` SignedTransaction `` should be fully
2017-07-27 12:14:08 +00:00
verified further by expanding with `` toLedgerTransaction `` and calling
`` verify `` . Further context specific and business checks should then be
made, because the `` Contract.verify `` is not allowed to access external
2017-10-01 22:33:15 +00:00
context. For example, the flow may need to check that the parties are the
2017-07-27 12:14:08 +00:00
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:
2016-11-28 13:39:34 +00:00
2018-11-14 14:16:22 +00:00
.. literalinclude :: example-code/src/main/kotlin/net/corda/docs/kotlin/txbuild/WorkflowTransactionBuildTutorial.kt
2016-11-28 13:39:34 +00:00
:language: kotlin
:start-after: DOCSTART 3
:end-before: DOCEND 3
2017-10-01 22:33:15 +00:00
:dedent: 8
2016-11-28 13:39:34 +00:00
2017-07-27 12:14:08 +00:00
After verification the remote flow will return its signature to the
originator. The originator should apply that signature to the starting
2016-11-28 13:39:34 +00:00
`` SignedTransaction `` and recheck the signatures match.
Committing the Transaction
--------------------------
2017-10-01 22:33:15 +00:00
Once all the signatures are applied to the `` SignedTransaction `` , the
final steps are notarisation and ensuring that all nodes record the fully-signed transaction. The
code for this is standardised in the `` FinalityFlow `` :
2016-11-28 13:39:34 +00:00
2018-11-14 14:16:22 +00:00
.. literalinclude :: example-code/src/main/kotlin/net/corda/docs/kotlin/txbuild/WorkflowTransactionBuildTutorial.kt
2016-11-28 13:39:34 +00:00
:language: kotlin
:start-after: DOCSTART 4
:end-before: DOCEND 4
2017-10-01 22:33:15 +00:00
:dedent: 8
2016-11-28 13:39:34 +00:00
Partially Visible Transactions
------------------------------
2017-07-27 12:14:08 +00:00
The discussion so far has assumed that the parties need full visibility
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
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
portions of the full transaction to restrict visibility to remote
parties. To do this one can use the
2017-10-01 22:33:15 +00:00
`` SignedTransaction.buildFilteredTransaction `` extension method to produce
2017-07-27 12:14:08 +00:00
a `` FilteredTransaction `` . The elements of the `` SignedTransaction ``
which we wish to be hide will be replaced with their secure hash. The
2017-10-01 22:33:15 +00:00
overall transaction id is still provable from the
2017-07-27 12:14:08 +00:00
`` FilteredTransaction `` preventing change of the private data, but we do
not expose that data to the other node directly. A full example of this
can be found in the `` NodeInterestRates `` Oracle code from the
`` irs-demo `` project which interacts with the `` RatesFixFlow `` flow.
2019-02-20 17:05:36 +00:00
Also, refer to the :doc: `tutorial-tear-offs` .