corda/docs/source/api-states.rst

154 lines
6.3 KiB
ReStructuredText
Raw Normal View History

2017-06-05 12:37:23 +00:00
API: States
===========
.. note:: Before reading this page, you should be familiar with the key concepts of :doc:`key-concepts-states`.
ContractState
-------------
In Corda, states are classes that implement ``ContractState``. The ``ContractState`` interface is defined as follows:
.. container:: codeset
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/contracts/Structures.kt
:language: kotlin
:start-after: DOCSTART 1
:end-before: DOCEND 1
Where:
* ``contract`` is the ``Contract`` class defining the constraints on transactions involving states of this type
* ``participants`` is a ``List`` of the ``AbstractParty`` who are considered to have a stake in the state. For example,
all the ``participants`` will:
* Need to sign a notary-change transaction for this state
* Receive any committed transactions involving this state as part of ``FinalityFlow``
The vault
---------
Each node has a vault, where it stores the states that are "relevant" to the node's owner. Whenever the node sees a
new transaction, it performs a relevancy check to decide whether to add each of the transaction's output states to
its vault. The default vault implementation decides whether a state is relevant as follows:
* The vault will store any state for which it is one of the ``participants``
* This behavior is overridden for states that implement ``LinearState`` or ``OwnableState`` (see below)
If a state is not considered relevant, the node will still store the transaction in its local storage, but it will
not track the transaction's states in its vault.
ContractState sub-interfaces
----------------------------
There are two common optional sub-interfaces of ``ContractState``:
* ``LinearState``, which helps represent objects that have a constant identity over time
* ``OwnableState``, which helps represent fungible assets
For example, a cash is an ``OwnableState`` - you don't have a specific piece of cash you are tracking over time, but
rather a total amount of cash that you can combine and divide at will. A contract, on the other hand, cannot be
merged with other contracts of the same type - it has a unique separate identity over time.
We can picture the hierarchy as follows:
.. image:: resources/state-hierarchy.png
LinearState
^^^^^^^^^^^
``LinearState`` models facts that have a constant identity over time. Remember that in Corda, states are immutable and
can't be updated directly. Instead, we represent an evolving fact as a sequence of states where every state is a
``LinearState`` that shares the same ``linearId``. Each sequence of linear states represents the lifecycle of a given
fact up to the current point in time. It represents the historic audit trail of how the fact evolved over time to its
current "state".
The ``LinearState`` interface is defined as follows:
.. container:: codeset
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/contracts/Structures.kt
:language: kotlin
:start-after: DOCSTART 2
:end-before: DOCEND 2
Where:
* ``linearId`` is a ``UniqueIdentifier`` that:
* Allows the successive versions of the fact to be linked over time
* Provides an ``externalId`` for referencing the state in external systems
* ``isRelevant(ourKeys: Set<PublicKey>)`` overrides the default vault implementation's relevancy check. You would
generally override it to check whether ``ourKeys`` is relevant to the state at hand in some way.
The vault tracks the head (i.e. the most recent version) of each ``LinearState`` chain (i.e. each sequence of
states all sharing a ``linearId``). To create a transaction updating a ``LinearState``, we retrieve the state from the
vault using its ``linearId``.
UniqueIdentifier
~~~~~~~~~~~~~~~~
``UniqueIdentifier`` is a combination of a (Java) ``UUID`` representing a globally unique 128 bit random number, and
an arbitrary string which can be paired with it. For instance the string may represent an existing "weak" (not
guaranteed unique) identifier for convenience purposes.
2017-06-05 12:37:23 +00:00
OwnableState
^^^^^^^^^^^^
``OwnableState`` models fungible assets. Fungible assets are assets for which it's the total amount held that is
important, rather than the actual units held. US dollars are an example of a fungible asset - we do not track the
individual dollar bills held, but rather the total amount of dollars.
The ``OwnableState`` interface is defined as follows:
.. container:: codeset
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/contracts/Structures.kt
:language: kotlin
:start-after: DOCSTART 3
:end-before: DOCEND 3
Where:
* ``owner`` is the ``PublicKey`` of the asset's owner
* ``OwnableState`` also override the default behavior of the vault's relevancy check. The default vault
implementation will track any ``OwnableState`` of which it is the owner.
2017-06-05 12:37:23 +00:00
* ``withNewOwner(newOwner: AbstractParty)`` creates an identical copy of the state, only with a new owner
2017-06-05 12:37:23 +00:00
Other interfaces
^^^^^^^^^^^^^^^^
``ContractState`` has several more sub-interfaces that can optionally be implemented:
* ``QueryableState``, which allows the state to be queried in the node's database using SQL (see
:doc:`api-persistence`)
2017-06-05 12:37:23 +00:00
* ``SchedulableState``, which allows us to schedule future actions for the state (e.g. a coupon on a bond) (see
:doc:`event-scheduling`)
User-defined fields
-------------------
Beyond implementing ``LinearState`` or ``OwnableState``, the definition of the state is up to the CorDapp developer.
You can define any additional class fields and methods you see fit.
For example, here is a relatively complex state definition, for a state representing cash:
.. container:: codeset
.. literalinclude:: ../../finance/src/main/kotlin/net/corda/finance/contracts/asset/Cash.kt
2017-06-05 12:37:23 +00:00
:language: kotlin
:start-after: DOCSTART 1
:end-before: DOCEND 1
TransactionState
----------------
When a ``ContractState`` is added to a ``TransactionBuilder``, it is wrapped in a ``TransactionState``:
.. container:: codeset
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/contracts/Structures.kt
:language: kotlin
:start-after: DOCSTART 4
:end-before: DOCEND 4
Where:
* ``data`` is the state to be stored on-ledger
* ``notary`` is the notary service for this state
* ``encumbrance`` points to another state that must also appear as an input to any transaction consuming this
state