Remove type-specific transaction builder. Normal transactions should use TransactionBuilder and notary change transactions are created directly.

This commit is contained in:
Andrius Dagys 2017-07-27 13:14:08 +01:00
parent 59edd6f9ae
commit 4ca8b8d681
54 changed files with 347 additions and 375 deletions

View File

@ -80,7 +80,7 @@ interface ContractState {
* 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
* 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
* they possess, since someone consumed that state during the notary change process.
*

View File

@ -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)
}
}

View File

@ -42,7 +42,7 @@ import java.security.PublicKey
*
* 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)
*
* builder.withItems(state, issueCommand)

View File

@ -51,7 +51,7 @@ class ContractUpgradeFlow<OldState : ContractState, out NewState : ContractState
privacySalt: PrivacySalt
): TransactionBuilder {
val contractUpgrade = upgradedContractClass.newInstance()
return TransactionType.General.Builder(stateRef.state.notary)
return TransactionBuilder(stateRef.state.notary)
.withItems(
stateRef,
contractUpgrade.upgrade(stateRef.state.data),

View File

@ -2,6 +2,7 @@ package net.corda.core.contracts
import net.corda.core.crypto.newSecureRandom
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.transactions.WireTransaction
import net.corda.testing.*
import net.corda.testing.contracts.DummyContract
@ -32,14 +33,14 @@ class TransactionGraphSearchTests : TestDependencyInjectionBase() {
val megaCorpServices = MockServices(MEGA_CORP_KEY)
val notaryServices = MockServices(DUMMY_NOTARY_KEY)
val originBuilder = TransactionType.General.Builder(DUMMY_NOTARY)
val originBuilder = TransactionBuilder(DUMMY_NOTARY)
originBuilder.addOutputState(DummyState(random31BitValue()))
originBuilder.addCommand(command, MEGA_CORP_PUBKEY)
val originPtx = megaCorpServices.signInitialTransaction(originBuilder)
val originTx = notaryServices.addSignature(originPtx)
val inputBuilder = TransactionType.General.Builder(DUMMY_NOTARY)
val inputBuilder = TransactionBuilder(DUMMY_NOTARY)
inputBuilder.addInputState(originTx.tx.outRef<DummyState>(0))
val inputPtx = megaCorpServices.signInitialTransaction(inputBuilder)

View File

@ -2,11 +2,11 @@ package net.corda.core.flows
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.contracts.Command
import net.corda.core.contracts.TransactionType
import net.corda.core.contracts.requireThat
import net.corda.core.getOrThrow
import net.corda.core.identity.Party
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.unwrap
import net.corda.testing.MINI_CORP_KEY
import net.corda.testing.contracts.DummyContract
@ -84,7 +84,7 @@ class CollectSignaturesFlowTests {
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
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 stx = subFlow(CollectSignaturesFlow(ptx))
val ftx = subFlow(FinalityFlow(stx)).single()
@ -104,7 +104,7 @@ class CollectSignaturesFlowTests {
override fun call(): SignedTransaction {
val notary = serviceHub.networkMapCache.notaryNodes.single().notaryIdentity
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 stx = subFlow(CollectSignaturesFlow(ptx))
val ftx = subFlow(FinalityFlow(stx)).single()

View File

@ -4,7 +4,6 @@ import net.corda.contracts.asset.Cash
import net.corda.core.contracts.Amount
import net.corda.core.contracts.GBP
import net.corda.core.contracts.Issued
import net.corda.core.contracts.TransactionType
import net.corda.core.getOrThrow
import net.corda.core.identity.Party
import net.corda.core.transactions.TransactionBuilder

View File

@ -67,7 +67,7 @@ class AttachmentClassLoaderTests : TestDependencyInjectionBase() {
fun generateInitial(owner: PartyAndReference, magicNumber: Int, notary: Party): TransactionBuilder {
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))
}
}

View File

@ -54,7 +54,7 @@ class TransactionSerializationTests : TestDependencyInjectionBase() {
@Before
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))
)
}
@ -86,7 +86,7 @@ class TransactionSerializationTests : TestDependencyInjectionBase() {
// If the signature was replaced in transit, we don't like it.
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))
val ptx2 = notaryServices.signInitialTransaction(tx2)

View File

@ -96,7 +96,6 @@ Where:
* ``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.
* ``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()
^^^^^^^^^^^^^

View File

@ -9,36 +9,6 @@ API: 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
--------------------
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
: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.

View File

@ -7,6 +7,9 @@ from the previous milestone release.
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``:
* ``PhysicalLocation`` was renamed to ``WorldMapLocation`` to emphasise that it doesn't need to map to a truly physical

View File

@ -5,7 +5,6 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import net.corda.contracts.asset.Cash;
import net.corda.core.contracts.*;
import net.corda.core.contracts.TransactionType.General;
import net.corda.core.crypto.DigitalSignature;
import net.corda.core.crypto.SecureHash;
import net.corda.core.flows.*;

View File

@ -3,7 +3,6 @@ package net.corda.docs
import co.paralleluniverse.fibers.Suspendable
import net.corda.contracts.asset.Cash
import net.corda.core.contracts.*
import net.corda.core.contracts.TransactionType.General
import net.corda.core.crypto.DigitalSignature
import net.corda.core.crypto.SecureHash
import net.corda.core.flows.*

View File

@ -5,7 +5,6 @@ import net.corda.contracts.asset.Cash
import net.corda.core.contracts.Amount
import net.corda.core.contracts.Issued
import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.TransactionType
import net.corda.core.crypto.DigitalSignature
import net.corda.core.crypto.SecureHash
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.serialization.CordaSerializable
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.unwrap
import java.util.*
@ -180,7 +180,7 @@ class ForeignExchangeFlow(val tradeId: String,
// This is the correct way to create a TransactionBuilder,
// do not construct directly.
// 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
val ourSigners = ourStates.inputs.map { it.state.data.owner.owningKey }.toSet()

View File

@ -16,6 +16,7 @@ import net.corda.core.node.services.linearHeadsOfType
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.LedgerTransaction
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.seconds
import net.corda.core.utilities.unwrap
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
val notary = serviceHub.networkMapCache.getAnyNotary()
// 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)))
tx.setTimeWindow(serviceHub.clock.instant(), 60.seconds)
// 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.
// Also add the Completed command with keys of all parties to signal the Tx purpose
// to the Contract verify method.
val tx = TransactionType.
General.
Builder(notary).
val tx = TransactionBuilder(notary).
withItems(
latestRecord,
newState,

View File

@ -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
// 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))
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.

View File

@ -4,102 +4,102 @@ Building transactions
Introduction
------------
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.
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.
The Basic Lifecycle Of Transactions
-----------------------------------
Transactions in Corda are constructed in stages and contain a number of
elements. In particular a transactions core data structure is the
``net.corda.core.transactions.WireTransaction``, which is usually
manipulated via a
``net.corda.core.contracts.General.TransactionBuilder`` and contains:
Transactions in Corda are constructed in stages and contain a number of
elements. In particular a transactions core data structure is the
``net.corda.core.transactions.WireTransaction``, which is usually
manipulated via a
``net.corda.core.transactions.TransactionBuilder`` and contains:
1. A set of Input state references that will be consumed by the final
accepted transaction.
1. A set of Input state references that will be consumed by the final
accepted transaction.
2. A set of Output states to create/replace the consumed states and thus
become the new latest versions of data on the ledger.
2. A set of Output states to create/replace the consumed states and thus
become the new latest versions of data on the ledger.
3. A set of ``Attachment`` items which can contain legal documents, contract
code, or private encrypted sections as an extension beyond the native
contract states.
3. A set of ``Attachment`` items which can contain legal documents, contract
code, or private encrypted sections as an extension beyond the native
contract states.
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
associated set of signer keys, which will be required to sign the
transaction.
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
associated set of signer keys, which will be required to sign the
transaction.
5. A signers list, which is populated by the ``TransactionBuilder`` to
be the union of the signers on the individual Command objects.
5. A signers list, which is populated by the ``TransactionBuilder`` to
be the union of the signers on the individual Command objects.
6. A notary identity to specify the Notary node which is tracking the
state consumption. (If the 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.)
6. A notary identity to specify the Notary node which is tracking the
state consumption. (If the 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.)
7. Optionally a timestamp that can used in the Notary to time bound the
period in which the proposed transaction stays valid.
7. Optionally a timestamp that can used in the Notary to time bound the
period in which the proposed transaction stays valid.
Typically, the ``WireTransaction`` should be regarded as a proposal and
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
model, which means that the input states are likely to be unknown to the
other node.
Typically, the ``WireTransaction`` should be regarded as a proposal and
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
model, which means that the input states are likely to be unknown to the
other node.
Once the proposed data is fully populated the flow code should freeze
the ``WireTransaction`` and form a ``SignedTransaction``. This is key to
the ledger agreement process, as once a flow has attached a nodes
signature it has stated that all details of the transaction are
acceptable to it. A flow should take care not to attach signatures to
intermediate data, which might be maliciously used to construct a
different ``SignedTransaction``. For instance in a foreign exchange
scenario we shouldn't send a ``SignedTransaction`` with only our sell
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
flows to receive back the ``DigitalSignature.WithKey`` of other parties
rather than a full ``SignedTransaction`` objects, because otherwise we
have to separately check that this is still the same
``SignedTransaction`` and not a malicious substitute.
Once the proposed data is fully populated the flow code should freeze
the ``WireTransaction`` and form a ``SignedTransaction``. This is key to
the ledger agreement process, as once a flow has attached a nodes
signature it has stated that all details of the transaction are
acceptable to it. A flow should take care not to attach signatures to
intermediate data, which might be maliciously used to construct a
different ``SignedTransaction``. For instance in a foreign exchange
scenario we shouldn't send a ``SignedTransaction`` with only our sell
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
flows to receive back the ``DigitalSignature.WithKey`` of other parties
rather than a full ``SignedTransaction`` objects, because otherwise we
have to separately check that this is still the same
``SignedTransaction`` and not a malicious substitute.
The final stage of committing the transaction to the ledger is to
notarise the ``SignedTransaction``, distribute this 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.
The final stage of committing the transaction to the ledger is to
notarise the ``SignedTransaction``, distribute this 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.
Gathering Inputs
----------------
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
searching the Vault via the ``VaultService`` interface on the
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
searching the Vault via the ``VaultService`` interface on the
``ServiceHub`` to locate the input states.
To give a few more specific details consider two simplified real world
scenarios. First, a basic foreign exchange Cash transaction. This
transaction needs to locate a set of funds to exchange. A flow
modelling this is implemented in ``FxTransactionBuildTutorial.kt``.
Second, a simple business model in which parties manually accept, or
reject each other's trade proposals which is implemented in
``WorkflowTransactionBuildTutorial.kt``. To run and explore these
examples using the IntelliJ IDE one can run/step the respective unit
tests in ``FxTransactionBuildTutorialTest.kt`` and
``WorkflowTransactionBuildTutorialTest.kt``, which drive the flows as
To give a few more specific details consider two simplified real world
scenarios. First, a basic foreign exchange Cash transaction. This
transaction needs to locate a set of funds to exchange. A flow
modelling this is implemented in ``FxTransactionBuildTutorial.kt``.
Second, a simple business model in which parties manually accept, or
reject each other's trade proposals which is implemented in
``WorkflowTransactionBuildTutorial.kt``. To run and explore these
examples using the IntelliJ IDE one can run/step the respective unit
tests in ``FxTransactionBuildTutorialTest.kt`` and
``WorkflowTransactionBuildTutorialTest.kt``, which drive the flows as
part of a simulated in-memory network of nodes.
.. |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$``
so that the ``Quasar`` instrumentation is correctly configured.
For the Cash transaction lets assume the cash resources are using the
standard ``CashState`` in the ``:financial`` Gradle module. The Cash
contract uses ``FungibleAsset`` states to model holdings of
interchangeable assets and allow the split/merge and summing of
states to meet a contractual obligation. We would normally use the
``generateSpend`` method on the ``VaultService`` to gather the required
amount of cash into a ``TransactionBuilder``, set the outputs and move
command. However, to elucidate more clearly example flow code is shown
here that will manually carry out the inputs queries using the lower
level ``VaultService``.
For the Cash transaction lets assume the cash resources are using the
standard ``CashState`` in the ``:financial`` Gradle module. The Cash
contract uses ``FungibleAsset`` states to model holdings of
interchangeable assets and allow the split/merge and summing of
states to meet a contractual obligation. We would normally use the
``generateSpend`` method on the ``VaultService`` to gather the required
amount of cash into a ``TransactionBuilder``, set the outputs and move
command. However, to elucidate more clearly example flow code is shown
here that will manually carry out the inputs queries using the lower
level ``VaultService``.
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt
:language: kotlin
:start-after: DOCSTART 1
:end-before: DOCEND 1
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
counterparty. However, the Corda privacy model means we do not know the
other nodes states. Our flow must therefore negotiate with the other
node for them to carry out a similar query and populate the inputs (See
the ``ForeignExchangeFlow`` for more details of the exchange). Having
identified a set of Input ``StateRef`` items we can then create the
output as discussed below.
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
counterparty. However, the Corda privacy model means we do not know the
other nodes states. Our flow must therefore negotiate with the other
node for them to carry out a similar query and populate the inputs (See
the ``ForeignExchangeFlow`` for more details of the exchange). Having
identified a set of Input ``StateRef`` items we can then create the
output as discussed below.
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
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
parameters to the flow to identify the states being operated upon. Thus
code to gather the latest input state would be:
@ -177,51 +177,51 @@ code to gather the latest input state would be:
Generating Commands
-------------------
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.
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
``CompositeKeys`` are added to the Command on the builder, which will be
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.
Another essential requirement for commands is that the correct set of
``CompositeKeys`` are added to the Command on the builder, which will be
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.
Generating Outputs
------------------
Having located a set of ``StateAndRefs`` as the transaction inputs, the
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
Having located a set of ``StateAndRefs`` as the transaction inputs, the
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
the latest revision.
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
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:
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
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:
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt
:language: kotlin
@ -231,15 +231,13 @@ the total cash. For example from the demo code:
Building the WireTransaction
----------------------------
Having gathered all the ingredients for the transaction we now need to
use a ``TransactionBuilder`` to construct the full ``WireTransaction``.
The initial ``TransactionBuilder`` should be created by calling the
``TransactionType.General.Builder`` method. (The other
``TransactionBuilder`` implementation is only used for the ``NotaryChange`` flow where
``ContractStates`` need moving to a different Notary.) At this point the
Notary to associate with the states should be recorded. Then we keep
adding inputs, outputs, commands and attachments to fill the
transaction. Examples of this process are:
Having gathered all the ingredients for the transaction we now need to
use a ``TransactionBuilder`` to construct the full ``WireTransaction``.
The initial ``TransactionBuilder`` should be created by calling the
``TransactionBuilder`` method. At this point the
Notary to associate with the states should be recorded. Then we keep
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
:language: kotlin
@ -254,51 +252,51 @@ transaction. Examples of this process are:
Completing the SignedTransaction
--------------------------------
Having created an initial ``WireTransaction`` and converted this to an
initial ``SignedTransaction`` the process of verifying and forming a
full ``SignedTransaction`` begins and then completes with the
notarisation. In practice this is a relatively stereotypical process,
because assuming the ``WireTransaction`` is correctly constructed the
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
Having created an initial ``WireTransaction`` and converted this to an
initial ``SignedTransaction`` the process of verifying and forming a
full ``SignedTransaction`` begins and then completes with the
notarisation. In practice this is a relatively stereotypical process,
because assuming the ``WireTransaction`` is correctly constructed the
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
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
notary and any other parties yet to apply their signature. The contents of the
``WireTransaction`` inside the ``SignedTransaction`` should be fully
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
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
expected for this specific flow. An example of this from the demo code is:
``WireTransaction`` inside the ``SignedTransaction`` should be fully
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
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
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
:language: kotlin
:start-after: DOCSTART 3
:end-before: DOCEND 3
After verification the remote flow will return its signature to the
originator. The originator should apply that signature to the starting
After verification the remote flow will return its signature to the
originator. The originator should apply that signature to the starting
``SignedTransaction`` and recheck the signatures match.
Committing the Transaction
--------------------------
Once all the party signatures are applied to the SignedTransaction the
final step is notarisation. This involves calling ``NotaryFlow.Client``
to confirm the transaction, consume the inputs and return its confirming
signature. Then the flow should ensure that all nodes end with all
signatures and that they call ``ServiceHub.recordTransactions``. The
code for this is standardised in the ``FinalityFlow``, or more explicitly
an example is:
Once all the party signatures are applied to the SignedTransaction the
final step is notarisation. This involves calling ``NotaryFlow.Client``
to confirm the transaction, consume the inputs and return its confirming
signature. Then the flow should ensure that all nodes end with all
signatures and that they call ``ServiceHub.recordTransactions``. The
code for this is standardised in the ``FinalityFlow``, or more explicitly
an example is:
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt
:language: kotlin
@ -308,19 +306,19 @@ an example is:
Partially Visible Transactions
------------------------------
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
``WireTransaction.buildFilteredTransaction`` extension method to produce
a ``FilteredTransaction``. The elements of the ``SignedTransaction``
which we wish to be hide will be replaced with their secure hash. The
overall transaction txid is still provable from the
``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.
Also, refer to the :doc:`merkle-trees` documentation.
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
``WireTransaction.buildFilteredTransaction`` extension method to produce
a ``FilteredTransaction``. The elements of the ``SignedTransaction``
which we wish to be hide will be replaced with their secure hash. The
overall transaction txid is still provable from the
``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.
Also, refer to the :doc:`merkle-trees` documentation.

View File

@ -39,7 +39,7 @@ Then we initialise the transaction builder:
.. 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.
Next we create a state object and assign ourselves as the owner. For this example we'll use a

View File

@ -1,4 +1,4 @@
package net.corda.contracts
package net.corda.contracts.isolated
import net.corda.core.contracts.*
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 {
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

View File

@ -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) {
State state = new State(issuance, issuance.getParty(), faceValue, maturityDate);
TransactionState output = new TransactionState<>(state, notary, encumbrance);
return new TransactionType.General.Builder(notary).withItems(output, new Command(new Commands.Issue(), issuance.getParty().getOwningKey()));
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) {

View File

@ -200,7 +200,7 @@ class CommercialPaper : Contract {
*/
fun generateIssue(issuance: PartyAndReference, faceValue: Amount<Issued<Currency>>, maturityDate: Instant, notary: Party): TransactionBuilder {
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))
}
/**

View File

@ -4,7 +4,6 @@ import co.paralleluniverse.fibers.Suspendable
import net.corda.contracts.asset.Cash
import net.corda.core.contracts.Amount
import net.corda.core.contracts.InsufficientBalanceException
import net.corda.core.contracts.TransactionType
import net.corda.core.contracts.issuedBy
import net.corda.core.flows.StartableByRPC
import net.corda.core.identity.Party
@ -36,7 +35,7 @@ class CashExitFlow(val amount: Amount<Currency>, val issueRef: OpaqueBytes, prog
@Throws(CashException::class)
override fun call(): AbstractCashFlow.Result {
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 exitStates = serviceHub.vaultService.unconsumedStatesForSpending<Cash.State>(amount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference))
val signers = try {

View File

@ -3,7 +3,6 @@ package net.corda.flows
import co.paralleluniverse.fibers.Suspendable
import net.corda.contracts.asset.Cash
import net.corda.core.contracts.Amount
import net.corda.core.contracts.TransactionType
import net.corda.core.contracts.issuedBy
import net.corda.core.flows.FinalityFlow
import net.corda.core.flows.StartableByRPC
@ -50,7 +49,7 @@ class CashIssueFlow(val amount: Amount<Currency>,
}
val anonymousRecipient = txIdentities[recipient]?.party ?: recipient
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 signers = Cash().generateIssue(builder, amount.issuedBy(issuer), anonymousRecipient, notary)
progressTracker.currentStep = SIGNING_TX

View File

@ -3,7 +3,6 @@ package net.corda.flows
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.contracts.Amount
import net.corda.core.contracts.InsufficientBalanceException
import net.corda.core.contracts.TransactionType
import net.corda.core.flows.StartableByRPC
import net.corda.core.flows.TransactionKeyFlow
import net.corda.core.identity.AnonymousPartyAndPath
@ -43,7 +42,7 @@ open class CashPaymentFlow(
}
val anonymousRecipient = txIdentities.get(recipient)?.party ?: recipient
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
val (spendTX, keysForSigning) = try {
serviceHub.vaultService.generateSpend(

View File

@ -178,7 +178,7 @@ object TwoPartyTradeFlow {
@Suspendable
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
val (tx, cashSigningPubKeys) = serviceHub.vaultService.generateSpend(ptx, tradeRequest.price, tradeRequest.sellerOwner)

View File

@ -10,6 +10,7 @@ import net.corda.core.node.services.Vault
import net.corda.core.node.services.VaultService
import net.corda.core.utilities.seconds
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.node.utilities.configureDatabase
import net.corda.testing.*
import net.corda.testing.node.MockServices
@ -263,7 +264,7 @@ class CommercialPaperTestsGeneric {
databaseAlice.transaction {
// Alice pays $9000 to BigCorp to own some of their debt.
moveTX = run {
val builder = TransactionType.General.Builder(DUMMY_NOTARY)
val builder = TransactionBuilder(DUMMY_NOTARY)
aliceVaultService.generateSpend(builder, 9000.DOLLARS, AnonymousParty(bigCorpServices.key.public))
CommercialPaper().generateMove(builder, issueTx.tx.outRef(0), AnonymousParty(aliceServices.key.public))
val ptx = aliceServices.signInitialTransaction(builder)
@ -284,7 +285,7 @@ class CommercialPaperTestsGeneric {
databaseBigCorp.transaction {
fun makeRedeemTX(time: Instant): Pair<SignedTransaction, UUID> {
val builder = TransactionType.General.Builder(DUMMY_NOTARY)
val builder = TransactionBuilder(DUMMY_NOTARY)
builder.setTimeWindow(time, 30.seconds)
CommercialPaper().generateRedeem(builder, moveTX.tx.outRef(1), bigCorpVaultService)
val ptx = aliceServices.signInitialTransaction(builder)

View File

@ -9,6 +9,7 @@ import net.corda.core.identity.Party
import net.corda.core.node.services.VaultService
import net.corda.core.node.services.unconsumedStates
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.transactions.WireTransaction
import net.corda.core.utilities.OpaqueBytes
import net.corda.node.services.vault.NodeVaultService
@ -155,7 +156,7 @@ class CashTests : TestDependencyInjectionBase() {
fun generateIssueRaw() {
initialiseTestSerialization()
// 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)
}.toWireTransaction()
assertTrue(tx.inputs.isEmpty())
@ -172,7 +173,7 @@ class CashTests : TestDependencyInjectionBase() {
initialiseTestSerialization()
// Test issuance from an issued amount
val amount = 100.DOLLARS `issued by` MINI_CORP.ref(12, 34)
val tx: WireTransaction = TransactionType.General.Builder(notary = null).apply {
val tx: WireTransaction = TransactionBuilder(notary = null).apply {
Cash().generateIssue(this, amount, owner = AnonymousParty(DUMMY_PUBKEY_1), notary = DUMMY_NOTARY)
}.toWireTransaction()
assertTrue(tx.inputs.isEmpty())
@ -244,13 +245,13 @@ class CashTests : TestDependencyInjectionBase() {
fun `reject issuance with inputs`() {
initialiseTestSerialization()
// 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)
val tx = miniCorpServices.signInitialTransaction(ptx)
// 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))
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.
*/
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)
return tx.toWireTransaction()
}
fun makeSpend(amount: Amount<Currency>, dest: AbstractParty): WireTransaction {
val tx = TransactionType.General.Builder(DUMMY_NOTARY)
val tx = TransactionBuilder(DUMMY_NOTARY)
database.transaction {
vault.generateSpend(tx, amount, dest)
}
@ -560,7 +561,7 @@ class CashTests : TestDependencyInjectionBase() {
fun generateExitWithEmptyVault() {
initialiseTestSerialization()
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())
}
}
@ -584,7 +585,7 @@ class CashTests : TestDependencyInjectionBase() {
initialiseTestSerialization()
database.transaction {
val tx = TransactionType.General.Builder(DUMMY_NOTARY)
val tx = TransactionBuilder(DUMMY_NOTARY)
vault.generateSpend(tx, 80.DOLLARS, ALICE, setOf(MINI_CORP))
assertEquals(vaultStatesUnconsumed.elementAt(2).ref, tx.inputStates()[0])

View File

@ -8,6 +8,7 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.testing.NULL_PARTY
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.AnonymousParty
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.NonEmptySet
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.days
@ -135,7 +136,7 @@ class ObligationTests {
initialiseTestSerialization()
// 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,
beneficiary = CHARLIE, notary = DUMMY_NOTARY)
}.toWireTransaction()
@ -214,14 +215,14 @@ class ObligationTests {
fun `reject issuance with inputs`() {
initialiseTestSerialization()
// 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,
beneficiary = MINI_CORP, notary = DUMMY_NOTARY)
}.toWireTransaction()
// 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))
Obligation<Currency>().generateIssue(ptx, MINI_CORP, megaCorpDollarSettlement, 100.DOLLARS.quantity,
beneficiary = MINI_CORP, notary = DUMMY_NOTARY)
@ -233,7 +234,7 @@ class ObligationTests {
initialiseTestSerialization()
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)
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)
}.toWireTransaction()
assertEquals(0, tx.outputs.size)
@ -245,7 +246,7 @@ class ObligationTests {
initialiseTestSerialization()
val obligationAliceToBob = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(ALICE, BOB)
val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE)
val tx = TransactionType.General.Builder(DUMMY_NOTARY).apply {
val tx = TransactionBuilder(DUMMY_NOTARY).apply {
Obligation<Currency>().generateCloseOutNetting(this, ALICE, obligationAliceToBob, obligationBobToAlice)
}.toWireTransaction()
assertEquals(1, tx.outputs.size)
@ -260,7 +261,7 @@ class ObligationTests {
initialiseTestSerialization()
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)
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)
}.toWireTransaction()
assertEquals(0, tx.outputs.size)
@ -272,7 +273,7 @@ class ObligationTests {
initialiseTestSerialization()
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB)
val obligationBobToAlice = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(BOB, ALICE)
val tx = TransactionType.General.Builder(null).apply {
val tx = TransactionBuilder(null).apply {
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBob.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice)
}.toWireTransaction()
assertEquals(1, tx.outputs.size)
@ -289,7 +290,7 @@ class ObligationTests {
val dueBefore = TEST_TX_TIME - 7.days
// 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))
Obligation<Currency>().generateCashIssue(this, ALICE, amount, dueBefore,
beneficiary = MINI_CORP, notary = DUMMY_NOTARY)
@ -298,7 +299,7 @@ class ObligationTests {
var stateAndRef = stx.tx.outRef<Obligation.State<Currency>>(0)
// 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)
}
var ptx = miniCorpServices.signInitialTransaction(tx, MINI_CORP_PUBKEY)
@ -310,7 +311,7 @@ class ObligationTests {
// And set it back
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)
}
ptx = miniCorpServices.signInitialTransaction(tx)
@ -324,18 +325,18 @@ class ObligationTests {
@Test
fun `generate settlement transaction`() {
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)
}.toWireTransaction()
// 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,
beneficiary = MINI_CORP, notary = DUMMY_NOTARY)
}.toWireTransaction()
// 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)
}.toWireTransaction()
assertEquals(2, settleTx.inputs.size)

View File

@ -8,7 +8,6 @@ import net.corda.contracts.asset.Cash
import net.corda.core.contracts.Command
import net.corda.core.contracts.CommandData
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.TransactionType
import net.corda.core.crypto.testing.NullSignature
import net.corda.core.identity.AnonymousParty
import net.corda.core.testing.*

View File

@ -3,7 +3,6 @@ package net.corda.node.services
import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionType
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.composite.CompositeKey
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.identity.Party
import net.corda.core.node.services.ServiceInfo
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.Try
import net.corda.node.internal.AbstractNode
@ -138,8 +138,8 @@ class BFTNotaryServiceTests {
private fun AbstractNode.signInitialTransaction(
notary: Party,
makeUnique: Boolean = false,
block: TransactionType.General.Builder.() -> Any?
) = services.signInitialTransaction(TransactionType.General.Builder(notary).apply {
block: TransactionBuilder.() -> Any?
) = services.signInitialTransaction(TransactionBuilder(notary).apply {
block()
if (makeUnique) {
addAttachment(SecureHash.randomSHA256())

View File

@ -3,13 +3,13 @@ package net.corda.node.services
import com.google.common.util.concurrent.Futures
import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionType
import net.corda.core.flows.NotaryError
import net.corda.core.flows.NotaryException
import net.corda.core.flows.NotaryFlow
import net.corda.core.getOrThrow
import net.corda.core.identity.Party
import net.corda.core.map
import net.corda.core.transactions.TransactionBuilder
import net.corda.node.internal.AbstractNode
import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.contracts.DummyContract
@ -34,13 +34,13 @@ class RaftNotaryServiceTests : NodeBasedTest() {
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 firstSpend = bankA.services.startFlow(NotaryFlow.Client(firstSpendTx))
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)
addOutputState(dummyState)
this

View File

@ -137,7 +137,7 @@ class NotaryChangeTests {
val stateB = 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))
addOutputState(stateA, notary, encumbrance = 2) // Encumbered by stateB
addOutputState(stateC, notary)

View File

@ -4,7 +4,6 @@ import io.requery.Persistable
import io.requery.kotlin.eq
import io.requery.sql.KotlinEntityDataStore
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionType
import net.corda.core.crypto.DigitalSignature
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.testing.NullPublicKey

View File

@ -9,6 +9,7 @@ import net.corda.core.identity.AbstractParty
import net.corda.core.node.ServiceHub
import net.corda.core.node.services.VaultService
import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.transactions.TransactionBuilder
import net.corda.testing.ALICE_KEY
import net.corda.testing.DUMMY_CA
import net.corda.testing.DUMMY_NOTARY
@ -280,7 +281,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
apply {
val freshKey = services.keyManagementService.freshKey()
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)
addCommand(Command(), freshKey)
}

View File

@ -8,6 +8,7 @@ import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.linearHeadsOfType
import net.corda.core.transactions.TransactionBuilder
import net.corda.node.services.network.NetworkMapService
import net.corda.node.services.statemachine.StateMachineManager
import net.corda.node.services.transactions.ValidatingNotaryService
@ -57,7 +58,7 @@ class ScheduledFlowTests {
serviceHub.myInfo.legalIdentity, destination)
val notary = serviceHub.networkMapCache.getAnyNotary()
val builder = TransactionType.General.Builder(notary)
val builder = TransactionBuilder(notary)
builder.withItems(scheduledState)
val tx = serviceHub.signInitialTransaction(builder)
subFlow(FinalityFlow(tx, setOf(serviceHub.myInfo.legalIdentity)))
@ -77,7 +78,7 @@ class ScheduledFlowTests {
require(!scheduledState.processed) { "State should not have been previously processed" }
val notary = state.state.notary
val newStateOutput = scheduledState.copy(processed = true)
val builder = TransactionType.General.Builder(notary)
val builder = TransactionBuilder(notary)
builder.withItems(state, newStateOutput)
val tx = serviceHub.signInitialTransaction(builder)
subFlow(FinalityFlow(tx, setOf(scheduledState.source, scheduledState.destination)))

View File

@ -1,7 +1,6 @@
package net.corda.node.services.persistence
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionType
import net.corda.core.crypto.DigitalSignature
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.testing.NullPublicKey

View File

@ -4,7 +4,6 @@ import co.paralleluniverse.fibers.Suspendable
import net.corda.contracts.asset.Cash
import net.corda.core.contracts.Amount
import net.corda.core.contracts.Issued
import net.corda.core.contracts.TransactionType
import net.corda.core.contracts.USD
import net.corda.core.flows.BroadcastTransactionFlow.NotifyTxRequest
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.node.services.unconsumedStates
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.node.services.NotifyTransactionHandler
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.MEGA_CORP
@ -50,7 +50,7 @@ class DataVendingServiceTests {
mockNet.runNetwork()
// 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)
// Complete the cash transaction, and then manually relay it
@ -80,7 +80,7 @@ class DataVendingServiceTests {
mockNet.runNetwork()
// 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)
// The transaction tries issuing MEGA_CORP cash, but we aren't the issuer, so it's invalid

View File

@ -3,7 +3,6 @@ package net.corda.node.services.transactions
import com.google.common.util.concurrent.ListenableFuture
import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionType
import net.corda.core.crypto.DigitalSignature
import net.corda.core.flows.NotaryError
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.utilities.seconds
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.node.internal.AbstractNode
import net.corda.node.services.network.NetworkMapService
import net.corda.testing.DUMMY_NOTARY
@ -50,7 +50,7 @@ class NotaryServiceTests {
fun `should sign a unique transaction with a valid time-window`() {
val stx = run {
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)
clientNode.services.signInitialTransaction(tx)
}
@ -64,7 +64,7 @@ class NotaryServiceTests {
fun `should sign a unique transaction without a time-window`() {
val stx = run {
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)
}
@ -77,7 +77,7 @@ class NotaryServiceTests {
fun `should report error for transaction with an invalid time-window`() {
val stx = run {
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)
clientNode.services.signInitialTransaction(tx)
}
@ -92,7 +92,7 @@ class NotaryServiceTests {
fun `should sign identical transaction multiple times (signing is idempotent)`() {
val stx = run {
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)
}
@ -110,11 +110,11 @@ class NotaryServiceTests {
fun `should report conflict when inputs are reused across transactions`() {
val inputState = issueState(clientNode)
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)
}
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))
clientNode.services.signInitialTransaction(tx)
}

View File

@ -4,7 +4,6 @@ import com.google.common.util.concurrent.ListenableFuture
import net.corda.core.contracts.Command
import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionType
import net.corda.core.crypto.DigitalSignature
import net.corda.core.flows.NotaryError
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.node.services.ServiceInfo
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.node.internal.AbstractNode
import net.corda.node.services.issueInvalidState
import net.corda.node.services.network.NetworkMapService
@ -52,7 +52,7 @@ class ValidatingNotaryServiceTests {
fun `should report error for invalid transaction dependency`() {
val stx = run {
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)
}
@ -70,7 +70,7 @@ class ValidatingNotaryServiceTests {
val inputState = issueState(clientNode)
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)
}

View File

@ -403,7 +403,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
val freshKey = services.legalIdentityKey
// 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)
}
val usefulTX = megaCorpServices.signInitialTransaction(usefulBuilder)
@ -416,7 +416,7 @@ class NodeVaultServiceTest : TestDependencyInjectionBase() {
assertEquals(3, vaultSvc.getTransactionNotes(usefulTX.id).count())
// 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)
}
val anotherTX = megaCorpServices.signInitialTransaction(anotherBuilder)

View File

@ -10,6 +10,7 @@ import net.corda.core.node.services.VaultService
import net.corda.core.node.services.consumedStates
import net.corda.core.node.services.unconsumedStates
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.node.services.database.HibernateConfiguration
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.utilities.CordaPersistence
@ -93,7 +94,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
database.transaction {
// A tx that sends us money.
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)
val usefulTX = megaCorpServices.signInitialTransaction(usefulBuilder)
@ -101,7 +102,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
services.recordTransactions(usefulTX)
// A tx that spends our money.
val spendTXBuilder = TransactionType.General.Builder(DUMMY_NOTARY)
val spendTXBuilder = TransactionBuilder(DUMMY_NOTARY)
vault.generateSpend(spendTXBuilder, 80.DOLLARS, BOB)
val spendPTX = services.signInitialTransaction(spendTXBuilder, freshKey)
val spendTX = notaryServices.addSignature(spendPTX)
@ -109,7 +110,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
assertEquals(100.DOLLARS, services.getCashBalance(USD))
// 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)
val irrelevantPTX = megaCorpServices.signInitialTransaction(irrelevantBuilder)
@ -147,7 +148,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
backgroundExecutor.submit {
database.transaction {
try {
val txn1Builder = TransactionType.General.Builder(DUMMY_NOTARY)
val txn1Builder = TransactionBuilder(DUMMY_NOTARY)
vault.generateSpend(txn1Builder, 60.DOLLARS, BOB)
val ptxn1 = notaryServices.signInitialTransaction(txn1Builder)
val txn1 = services.addSignature(ptxn1, freshKey)
@ -177,7 +178,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
backgroundExecutor.submit {
database.transaction {
try {
val txn2Builder = TransactionType.General.Builder(DUMMY_NOTARY)
val txn2Builder = TransactionBuilder(DUMMY_NOTARY)
vault.generateSpend(txn2Builder, 80.DOLLARS, BOB)
val ptxn2 = notaryServices.signInitialTransaction(txn2Builder)
val txn2 = services.addSignature(ptxn2, freshKey)
@ -219,7 +220,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
val linearId = UniqueIdentifier()
// 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)))
}
@ -240,7 +241,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
val linearId = UniqueIdentifier()
// 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)))
val dummyIssuePtx = notaryServices.signInitialTransaction(dummyIssueBuilder)
val dummyIssue = services.addSignature(dummyIssuePtx)
@ -251,7 +252,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
assertThat(vault.unconsumedStates<DummyLinearContract.State>()).hasSize(1)
// 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)))
addInputState(dummyIssue.tx.outRef<LinearState>(0))
}
@ -283,7 +284,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
database.transaction {
// A tx that spends our money.
val spendTXBuilder = TransactionType.General.Builder(DUMMY_NOTARY)
val spendTXBuilder = TransactionBuilder(DUMMY_NOTARY)
vault.generateSpend(spendTXBuilder, 80.DOLLARS, BOB)
val spendPTX = notaryServices.signInitialTransaction(spendTXBuilder)
val spendTX = services.addSignature(spendPTX, freshKey)
@ -313,7 +314,7 @@ class VaultWithCashTest : TestDependencyInjectionBase() {
linearStates.forEach { println(it.state.data.linearId) }
// 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(DummyDealContract.State(ref = "999", participants = listOf(freshIdentity)))
addInputState(linearStates.first())

View File

@ -5,7 +5,6 @@ import joptsimple.OptionParser
import net.corda.client.rpc.CordaRPCClient
import net.corda.core.contracts.Contract
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.TransactionType
import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FinalityFlow
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.transactions.LedgerTransaction
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.ProgressTracker
import net.corda.testing.DUMMY_BANK_B
@ -106,7 +106,7 @@ class AttachmentDemoFlow(val otherSide: Party, val hash: SecureHash.SHA256) : Fl
@Suspendable
override fun call(): SignedTransaction {
// 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.addAttachment(hash)

View File

@ -783,7 +783,7 @@ class InterestRateSwap : Contract {
// Put all the above into a new State object.
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 {

View File

@ -61,7 +61,7 @@ object FixingFlow {
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 oracleParty = oracle.serviceIdentities(handshake.payload.oracleType).first()

View File

@ -208,7 +208,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
n2.database.transaction {
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 oracle = n2.info.serviceIdentities(NodeInterestRates.Oracle.type).first()
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)
}

View File

@ -3,6 +3,7 @@ package net.corda.irs.contract
import net.corda.contracts.*
import net.corda.core.contracts.*
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.seconds
import net.corda.testing.*
import net.corda.testing.node.MockServices
@ -305,7 +306,7 @@ class IRSTests : TestDependencyInjectionBase() {
while (true) {
val nextFix: FixOf = currentIRS().nextFixingOf() ?: break
val fixTX: SignedTransaction = run {
val tx = TransactionType.General.Builder(DUMMY_NOTARY)
val tx = TransactionBuilder(DUMMY_NOTARY)
val fixing = Fix(nextFix, "0.052".percent.value)
InterestRateSwap().generateFix(tx, previousTXN.tx.outRef(0), fixing)
tx.setTimeWindow(TEST_TX_TIME, 30.seconds)

View File

@ -2,7 +2,6 @@ package net.corda.vega.contracts
import net.corda.contracts.DealState
import net.corda.core.contracts.Command
import net.corda.core.contracts.TransactionType
import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.crypto.keys
import net.corda.core.identity.AbstractParty
@ -29,6 +28,6 @@ data class IRSState(val swap: SwapData,
override fun generateAgreement(notary: Party): TransactionBuilder {
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 }))
}
}

View File

@ -42,7 +42,7 @@ data class PortfolioState(val portfolio: List<StateRef>,
}
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 {
@ -50,7 +50,7 @@ data class PortfolioState(val portfolio: List<StateRef>,
val portfolio = updatedValue.portfolio ?: portfolio
val valuation = updatedValue.valuation ?: valuation
val tx = TransactionType.General.Builder(notary)
val tx = TransactionBuilder(notary)
tx.addInputState(oldState)
tx.addOutputState(copy(portfolio = portfolio, valuation = valuation))
tx.addCommand(PortfolioSwap.Commands.Update(), participants.map { it.owningKey })

View File

@ -16,6 +16,7 @@ import net.corda.core.identity.Party
import net.corda.core.node.NodeInfo
import net.corda.core.utilities.seconds
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker
import net.corda.flows.TwoPartyTradeFlow
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.
val move: SignedTransaction = run {
val builder = TransactionType.General.Builder(notaryNode.notaryIdentity)
val builder = TransactionBuilder(notaryNode.notaryIdentity)
CommercialPaper().generateMove(builder, issuance.tx.outRef(0), ownedBy)
val stx = serviceHub.signInitialTransaction(builder)
subFlow(FinalityFlow(stx)).single()

View File

@ -50,10 +50,10 @@ data class DummyContract(override val legalContractReference: SecureHash = Secur
val owners = listOf(owner) + otherOwners
return if (owners.size == 1) {
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 {
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())
val priorState = priors[0].state.data
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(),
/* COMMAND */ Command(cmd, priorState.owner.owningKey),
/* OUTPUT */ state

View File

@ -5,6 +5,7 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.flows.ContractUpgradeFlow
import net.corda.core.identity.AbstractParty
import net.corda.core.transactions.LedgerTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.transactions.WireTransaction
// The dummy contract doesn't do anything useful. It exists for testing purposes.
@ -51,7 +52,7 @@ class DummyContractV2 : UpgradedContract<DummyContract.State, DummyContractV2.St
require(states.isNotEmpty())
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 {
addInputState(it)
addOutputState(upgrade(it.state.data))

View File

@ -13,6 +13,7 @@ import net.corda.core.node.ServiceHub
import net.corda.core.node.services.Vault
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.testing.CHARLIE
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.DUMMY_NOTARY_KEY
@ -30,7 +31,7 @@ fun ServiceHub.fillWithSomeTestDeals(dealIds: List<String>,
val transactions: List<SignedTransaction> = dealIds.map {
// 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)))
signWith(DUMMY_NOTARY_KEY)
}
@ -60,7 +61,7 @@ fun ServiceHub.fillWithSomeTestLinearStates(numberToCreate: Int,
val transactions: List<SignedTransaction> = (1..numberToCreate).map {
// Issue a Linear state
val dummyIssue = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
val dummyIssue = TransactionBuilder(notary = DUMMY_NOTARY).apply {
addOutputState(DummyLinearContract.State(
linearId = UniqueIdentifier(externalId),
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.
val cash = Cash()
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)
issuance.signWith(issuerKey)
@ -139,7 +140,7 @@ fun ServiceHub.fillWithSomeTestCommodity(amount: Amount<Commodity>,
val me = AnonymousParty(myKey)
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)
issuance.signWith(issuerKey)
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>>) {
// Create a txn consuming different contract types
states.forEach {
val consumedTx = TransactionType.General.Builder(notary = DUMMY_NOTARY).apply {
val consumedTx = TransactionBuilder(notary = DUMMY_NOTARY).apply {
addInputState(it)
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction()
@ -191,7 +192,7 @@ fun <T : LinearState> ServiceHub.consume(states: List<StateAndRef<T>>) {
fun <T : LinearState> ServiceHub.consumeAndProduce(stateAndRef: StateAndRef<T>): StateAndRef<T> {
// 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)
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction()
@ -199,7 +200,7 @@ fun <T : LinearState> ServiceHub.consumeAndProduce(stateAndRef: StateAndRef<T>):
recordTransactions(consumedTx)
// 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,
participants = stateAndRef.state.data.participants))
signWith(DUMMY_NOTARY_KEY)
@ -224,7 +225,7 @@ fun ServiceHub.evolveLinearState(linearState: StateAndRef<LinearState>) : StateA
@JvmOverloads
fun ServiceHub.consumeCash(amount: Amount<Currency>, to: Party = CHARLIE): Vault<Cash.State> {
// 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)
signWith(DUMMY_NOTARY_KEY)
}.toSignedTransaction(checkSufficientSignatures = false)