Docsite reorg ahead of beta launch.
@ -12,8 +12,6 @@ Corda is a decentralised database system in which nodes trust each other as litt
|
||||
* "Notary" infrastructure to validate uniqueness of transactions
|
||||
* Written as a platform for distributed apps called CorDapps
|
||||
* Written in [Kotlin](https://kotlinlang.org), targeting the JVM
|
||||
|
||||
Read our full and planned feature list [here](https://docs.corda.net/inthebox.html).
|
||||
|
||||
## Getting started
|
||||
|
||||
|
@ -54,6 +54,7 @@ interface MultilateralNettableState<out T : Any> {
|
||||
interface NettableState<N : BilateralNettableState<N>, out T : Any> : BilateralNettableState<N>,
|
||||
MultilateralNettableState<T>
|
||||
|
||||
// DOCSTART 1
|
||||
/**
|
||||
* A contract state (or just "state") contains opaque data used by a contract program. It can be thought of as a disk
|
||||
* file that the program can use to persist data across transactions. States are immutable: once created they are never
|
||||
@ -116,7 +117,9 @@ interface ContractState {
|
||||
*/
|
||||
val participants: List<AbstractParty>
|
||||
}
|
||||
// DOCEND 1
|
||||
|
||||
// DOCSTART 4
|
||||
/**
|
||||
* A wrapper for [ContractState] containing additional platform-level state information.
|
||||
* This is the definitive state that is stored on the ledger and used in transaction outputs.
|
||||
@ -145,6 +148,7 @@ data class TransactionState<out T : ContractState> @JvmOverloads constructor(
|
||||
* otherwise the transaction is not valid.
|
||||
*/
|
||||
val encumbrance: Int? = null)
|
||||
// DOCEND 4
|
||||
|
||||
/** Wraps the [ContractState] in a [TransactionState] object */
|
||||
infix fun <T : ContractState> T.`with notary`(newNotary: Party) = withNotary(newNotary)
|
||||
@ -169,6 +173,7 @@ data class Issued<out P : Any>(val issuer: PartyAndReference, val product: P) {
|
||||
*/
|
||||
fun <T : Any> Amount<Issued<T>>.withoutIssuer(): Amount<T> = Amount(quantity, token.product)
|
||||
|
||||
// DOCSTART 3
|
||||
/**
|
||||
* A contract state that can have a single owner.
|
||||
*/
|
||||
@ -179,6 +184,7 @@ interface OwnableState : ContractState {
|
||||
/** Copies the underlying data structure, replacing the owner field with this new value and leaving the rest alone */
|
||||
fun withNewOwner(newOwner: AbstractParty): Pair<CommandData, OwnableState>
|
||||
}
|
||||
// DOCEND 3
|
||||
|
||||
/** Something which is scheduled to happen at a point in time */
|
||||
interface Scheduled {
|
||||
@ -207,6 +213,7 @@ data class ScheduledStateRef(val ref: StateRef, override val scheduledAt: Instan
|
||||
*/
|
||||
data class ScheduledActivity(val logicRef: FlowLogicRef, override val scheduledAt: Instant) : Scheduled
|
||||
|
||||
// DOCSTART 2
|
||||
/**
|
||||
* A state that evolves by superseding itself, all of which share the common "linearId".
|
||||
*
|
||||
@ -245,6 +252,7 @@ interface LinearState : ContractState {
|
||||
}
|
||||
}
|
||||
}
|
||||
// DOCEND 2
|
||||
|
||||
interface SchedulableState : ContractState {
|
||||
/**
|
||||
@ -325,13 +333,17 @@ fun ContractState.hash(): SecureHash = SecureHash.sha256(serialize().bytes)
|
||||
* transaction defined the state and where in that transaction it was.
|
||||
*/
|
||||
@CordaSerializable
|
||||
// DOCSTART 8
|
||||
data class StateRef(val txhash: SecureHash, val index: Int) {
|
||||
override fun toString() = "$txhash($index)"
|
||||
}
|
||||
// DOCEND 8
|
||||
|
||||
/** A StateAndRef is simply a (state, ref) pair. For instance, a vault (which holds available assets) contains these. */
|
||||
@CordaSerializable
|
||||
// DOCSTART 7
|
||||
data class StateAndRef<out T : ContractState>(val state: TransactionState<T>, val ref: StateRef)
|
||||
// DOCEND 7
|
||||
|
||||
/** Filters a list of [StateAndRef] objects according to the type of the states */
|
||||
inline fun <reified T : ContractState> Iterable<StateAndRef<ContractState>>.filterStatesOfType(): List<StateAndRef<T>> {
|
||||
@ -359,7 +371,9 @@ abstract class TypeOnlyCommandData : CommandData {
|
||||
|
||||
/** Command data/content plus pubkey pair: the signature is stored at the end of the serialized bytes */
|
||||
@CordaSerializable
|
||||
// DOCSTART 9
|
||||
data class Command(val value: CommandData, val signers: List<PublicKey>) {
|
||||
// DOCEND 9
|
||||
init {
|
||||
require(signers.isNotEmpty())
|
||||
}
|
||||
@ -395,6 +409,7 @@ interface NetCommand : CommandData {
|
||||
/** Indicates that this transaction replaces the inputs contract state to another contract state */
|
||||
data class UpgradeCommand(val upgradedContractClass: Class<out UpgradedContract<*, *>>) : CommandData
|
||||
|
||||
// DOCSTART 6
|
||||
/** Wraps an object that was signed by a public key, which may be a well known/recognised institutional key. */
|
||||
@CordaSerializable
|
||||
data class AuthenticatedObject<out T : Any>(
|
||||
@ -403,6 +418,7 @@ data class AuthenticatedObject<out T : Any>(
|
||||
val signingParties: List<Party>,
|
||||
val value: T
|
||||
)
|
||||
// DOCEND 6
|
||||
|
||||
/**
|
||||
* A time-window is required for validation/notarization purposes.
|
||||
@ -457,6 +473,7 @@ class TimeWindow private constructor(
|
||||
override fun toString() = "TimeWindow(fromTime=$fromTime, untilTime=$untilTime)"
|
||||
}
|
||||
|
||||
// DOCSTART 5
|
||||
/**
|
||||
* Implemented by a program that implements business logic on the shared ledger. All participants run this code for
|
||||
* every [LedgerTransaction] they see on the network, for every input and output state. All contracts must accept the
|
||||
@ -482,6 +499,7 @@ interface Contract {
|
||||
*/
|
||||
val legalContractReference: SecureHash
|
||||
}
|
||||
// DOCEND 5
|
||||
|
||||
/**
|
||||
* Interface which can upgrade state objects issued by a contract to a new state object issued by a different contract.
|
||||
|
@ -13,6 +13,7 @@ import java.util.*
|
||||
* A transaction to be passed as input to a contract verification function. Defines helper methods to
|
||||
* simplify verification logic in contracts.
|
||||
*/
|
||||
// DOCSTART 1
|
||||
data class TransactionForContract(val inputs: List<ContractState>,
|
||||
val outputs: List<ContractState>,
|
||||
val attachments: List<Attachment>,
|
||||
@ -20,6 +21,7 @@ data class TransactionForContract(val inputs: List<ContractState>,
|
||||
val origHash: SecureHash,
|
||||
val inputNotary: Party? = null,
|
||||
val timeWindow: TimeWindow? = null) {
|
||||
// DOCEND 1
|
||||
override fun hashCode() = origHash.hashCode()
|
||||
override fun equals(other: Any?) = other is TransactionForContract && other.origHash == origHash
|
||||
|
||||
@ -37,6 +39,7 @@ data class TransactionForContract(val inputs: List<ContractState>,
|
||||
* currency. To solve this, you would use groupStates with a type of Cash.State and a selector that returns the
|
||||
* currency field: the resulting list can then be iterated over to perform the per-currency calculation.
|
||||
*/
|
||||
// DOCSTART 2
|
||||
fun <T : ContractState, K : Any> groupStates(ofType: Class<T>, selector: (T) -> K): List<InOutGroup<T, K>> {
|
||||
val inputs = inputs.filterIsInstance(ofType)
|
||||
val outputs = outputs.filterIsInstance(ofType)
|
||||
@ -47,6 +50,7 @@ data class TransactionForContract(val inputs: List<ContractState>,
|
||||
@Suppress("DEPRECATION")
|
||||
return groupStatesInternal(inGroups, outGroups)
|
||||
}
|
||||
// DOCEND 2
|
||||
|
||||
/** See the documentation for the reflection-based version of [groupStates] */
|
||||
inline fun <reified T : ContractState, K : Any> groupStates(selector: (T) -> K): List<InOutGroup<T, K>> {
|
||||
@ -83,7 +87,9 @@ data class TransactionForContract(val inputs: List<ContractState>,
|
||||
* up on both sides of the transaction, but the values must be summed independently per currency. Grouping can
|
||||
* be used to simplify this logic.
|
||||
*/
|
||||
// DOCSTART 3
|
||||
data class InOutGroup<out T : ContractState, out K : Any>(val inputs: List<T>, val outputs: List<T>, val groupingKey: K)
|
||||
// DOCEND 3
|
||||
}
|
||||
|
||||
class TransactionResolutionException(val hash: SecureHash) : FlowException() {
|
||||
|
@ -2,6 +2,7 @@ package net.corda.core.flows
|
||||
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
|
||||
// DOCSTART 1
|
||||
/**
|
||||
* Exception which can be thrown by a [FlowLogic] at any point in its logic to unexpectedly bring it to a permanent end.
|
||||
* The exception will propagate to all counterparty flows and will be thrown on their end the next time they wait on a
|
||||
@ -17,6 +18,7 @@ open class FlowException(override val message: String?, override val cause: Thro
|
||||
constructor(cause: Throwable?) : this(cause?.toString(), cause)
|
||||
constructor() : this(null, null)
|
||||
}
|
||||
// DOCEND 1
|
||||
|
||||
/**
|
||||
* Thrown when a flow session ends unexpectedly due to a type mismatch (the other side sent an object of a type
|
||||
|
@ -26,9 +26,11 @@ import java.util.*
|
||||
* when verifying composite key signatures, but may be used as individual signatures where a single key is expected to
|
||||
* sign.
|
||||
*/
|
||||
// DOCSTART 1
|
||||
data class SignedTransaction(val txBits: SerializedBytes<WireTransaction>,
|
||||
val sigs: List<DigitalSignature.WithKey>
|
||||
) : NamedByHash {
|
||||
// DOCEND 1
|
||||
init {
|
||||
require(sigs.isNotEmpty())
|
||||
}
|
||||
@ -64,8 +66,10 @@ data class SignedTransaction(val txBits: SerializedBytes<WireTransaction>,
|
||||
* @throws SignatureException if any signatures are invalid or unrecognised.
|
||||
* @throws SignaturesMissingException if any signatures should have been present but were not.
|
||||
*/
|
||||
// DOCSTART 2
|
||||
@Throws(SignatureException::class)
|
||||
fun verifySignatures(vararg allowedToBeMissing: PublicKey): WireTransaction {
|
||||
// DOCEND 2
|
||||
// Embedded WireTransaction is not deserialised until after we check the signatures.
|
||||
checkSignaturesAreValid()
|
||||
|
||||
|
@ -77,6 +77,7 @@ open class TransactionBuilder(
|
||||
this.timeWindow = timeWindow
|
||||
}
|
||||
|
||||
// DOCSTART 1
|
||||
/** A more convenient way to add items to this transaction that calls the add* methods for you based on type */
|
||||
fun withItems(vararg items: Any): TransactionBuilder {
|
||||
for (t in items) {
|
||||
@ -91,6 +92,7 @@ open class TransactionBuilder(
|
||||
}
|
||||
return this
|
||||
}
|
||||
// DOCEND 1
|
||||
|
||||
/** The signatures that have been collected so far - might be incomplete! */
|
||||
protected val currentSigs = arrayListOf<DigitalSignature.WithKey>()
|
||||
|
@ -123,6 +123,7 @@ class CollectSignaturesFlow(val partiallySignedTx: SignedTransaction,
|
||||
partyNode.legalIdentity
|
||||
}
|
||||
|
||||
// DOCSTART 1
|
||||
/**
|
||||
* Get and check the required signature.
|
||||
*/
|
||||
@ -132,6 +133,7 @@ class CollectSignaturesFlow(val partiallySignedTx: SignedTransaction,
|
||||
it
|
||||
}
|
||||
}
|
||||
// DOCEND 1
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,7 +99,10 @@ object TwoPartyDealFlow {
|
||||
logger.trace { "Signed proposed transaction." }
|
||||
|
||||
progressTracker.currentStep = COLLECTING_SIGNATURES
|
||||
|
||||
// DOCSTART 1
|
||||
val stx = subFlow(CollectSignaturesFlow(ptx))
|
||||
// DOCEND 1
|
||||
|
||||
logger.trace { "Got signatures from other party, verifying ... " }
|
||||
|
||||
|
309
docs/source/api-contracts.rst
Normal file
@ -0,0 +1,309 @@
|
||||
.. highlight:: kotlin
|
||||
.. raw:: html
|
||||
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/codesets.js"></script>
|
||||
|
||||
API: Contracts
|
||||
==============
|
||||
|
||||
.. note:: Before reading this page, you should be familiar with the key concepts of :doc:`key-concepts-contracts`.
|
||||
|
||||
All Corda contracts are JVM classes that implement ``net.corda.core.contracts.Contract``.
|
||||
|
||||
The ``Contract`` interface is defined as follows:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/contracts/Structures.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 5
|
||||
:end-before: DOCEND 5
|
||||
|
||||
Where:
|
||||
|
||||
* ``verify(tx: TransactionForContract)`` determines whether transactions involving states which reference this
|
||||
contract type are valid
|
||||
* ``legalContractReference`` is the hash of the legal prose contract that ``verify`` seeks to express in code
|
||||
|
||||
verify()
|
||||
--------
|
||||
|
||||
``verify()`` is a method that doesn't return anything and takes a ``TransactionForContract`` as a parameter. It
|
||||
either throws an exception if the transaction is considered invalid, or returns normally if the transaction is
|
||||
considered valid.
|
||||
|
||||
``verify()`` is executed in a sandbox. It does not have access to the enclosing scope, and is not able to access
|
||||
the network or perform any other I/O. It only has access to the properties defined on ``TransactionForContract`` when
|
||||
establishing whether a transaction is valid.
|
||||
|
||||
The two simplest ``verify`` functions are the one that accepts all transactions, and the one that rejects all
|
||||
transactions.
|
||||
|
||||
Here is the ``verify`` that accepts all transactions:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
override fun verify(tx: TransactionForContract) {
|
||||
// Always accepts!
|
||||
}
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
@Override
|
||||
public void verify(TransactionForContract tx) {
|
||||
// Always accepts!
|
||||
}
|
||||
|
||||
And here is the ``verify`` that rejects all transactions:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
override fun verify(tx: TransactionForContract) {
|
||||
throw IllegalArgumentException("Always rejects!")
|
||||
}
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
@Override
|
||||
public void verify(TransactionForContract tx) {
|
||||
throw new IllegalArgumentException("Always rejects!");
|
||||
}
|
||||
|
||||
TransactionForContract
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ``TransactionForContract`` object passed into ``verify()`` represents the full set of information available to
|
||||
``verify()`` when deciding whether to accept or reject the transaction. It has the following properties:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/contracts/TransactionVerification.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 1
|
||||
:end-before: DOCEND 1
|
||||
|
||||
Where:
|
||||
|
||||
* ``inputs`` is a list of the transaction's inputs
|
||||
* ``outputs`` is a list of the transaction's outputs
|
||||
* ``attachments`` is a list of the transaction's attachments
|
||||
* ``commands`` is a list of the transaction's commands, and their associated signatures
|
||||
* ``origHash`` is the transaction's hash
|
||||
* ``inputNotary`` is the transaction's notary
|
||||
* ``timestamp`` is the transaction's timestamp
|
||||
|
||||
requireThat()
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Instead of throwing exceptions manually to reject a transaction, we can use the ``requireThat`` DSL:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
requireThat {
|
||||
"No inputs should be consumed when issuing an X." using (tx.inputs.isEmpty())
|
||||
"Only one output state should be created." using (tx.outputs.size == 1)
|
||||
val out = tx.outputs.single() as XState
|
||||
"The sender and the recipient cannot be the same entity." using (out.sender != out.recipient)
|
||||
"All of the participants must be signers." using (command.signers.containsAll(out.participants))
|
||||
"The X's value must be non-negative." using (out.x.value > 0)
|
||||
}
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
requireThat(require -> {
|
||||
require.using("No inputs should be consumed when issuing an X.", tx.getInputs().isEmpty());
|
||||
require.using("Only one output state should be created.", tx.getOutputs().size() == 1);
|
||||
final XState out = (XState) tx.getOutputs().get(0);
|
||||
require.using("The sender and the recipient cannot be the same entity.", out.getSender() != out.getRecipient());
|
||||
require.using("All of the participants must be signers.", command.getSigners().containsAll(out.getParticipants()));
|
||||
require.using("The X's value must be non-negative.", out.getX().getValue() > 0);
|
||||
return null;
|
||||
});
|
||||
|
||||
For each <``String``, ``Boolean``> pair within ``requireThat``, if the boolean condition is false, an
|
||||
``IllegalArgumentException`` is thrown with the corresponding string as the exception message. In turn, this
|
||||
exception will cause the transaction to be rejected.
|
||||
|
||||
Commands
|
||||
^^^^^^^^
|
||||
|
||||
``TransactionForContract`` contains the commands as a list of ``AuthenticatedObject`` instances.
|
||||
``AuthenticatedObject`` pairs an object with a list of signers. In this case, ``AuthenticatedObject`` pairs a command
|
||||
with a list of the entities that are required to sign a transaction where this command is present:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/contracts/Structures.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 6
|
||||
:end-before: DOCEND 6
|
||||
|
||||
Where:
|
||||
|
||||
* ``signers`` is the list of each signer's ``PublicKey``
|
||||
* ``signingParties`` is the list of the signer's identities, if known
|
||||
* ``value`` is the object being signed (a command, in this case)
|
||||
|
||||
Extracting commands
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
You can use the ``requireSingleCommand()`` helper method to extract commands.
|
||||
|
||||
``<C : CommandData> Collection<AuthenticatedObject<CommandData>>.requireSingleCommand(klass: Class<C>)`` asserts that
|
||||
the transaction contains exactly one command of type ``T``, and returns it. If there is not exactly one command of this
|
||||
type in the transaction, an exception is thrown, rejecting the transaction.
|
||||
|
||||
For ``requireSingleCommand`` to work, all the commands that we wish to match against must be grouped using the same
|
||||
marker interface.
|
||||
|
||||
Here is an example of using ``requireSingleCommand`` to extract a transaction's command and using it to fork the
|
||||
execution of ``verify()``:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
class XContract : Contract {
|
||||
interface Commands : CommandData {
|
||||
class Issue : TypeOnlyCommandData(), Commands
|
||||
class Transfer : TypeOnlyCommandData(), Commands
|
||||
}
|
||||
|
||||
override fun verify(tx: TransactionForContract) {
|
||||
val command = tx.commands.requireSingleCommand<Commands>()
|
||||
|
||||
when (command.value) {
|
||||
is Commands.Issue -> {
|
||||
// Issuance verification logic.
|
||||
}
|
||||
is Commands.Transfer -> {
|
||||
// Transfer verification logic.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val legalContractReference: SecureHash = SecureHash.sha256("X contract hash")
|
||||
}
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
public class XContract implements Contract {
|
||||
public interface Commands extends CommandData {
|
||||
class Issue extends TypeOnlyCommandData implements Commands {}
|
||||
class Transfer extends TypeOnlyCommandData implements Commands {}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verify(TransactionForContract tx) {
|
||||
final AuthenticatedObject<Commands> command = requireSingleCommand(tx.getCommands(), Commands.class);
|
||||
|
||||
if (command.getValue() instanceof Commands.Issue) {
|
||||
// Issuance verification logic.
|
||||
} else if (command.getValue() instanceof Commands.Transfer) {
|
||||
// Transfer verification logic.
|
||||
}
|
||||
}
|
||||
|
||||
private final SecureHash legalContractReference = SecureHash.sha256("X contract hash");
|
||||
@Override public final SecureHash getLegalContractReference() { return legalContractReference; }
|
||||
}
|
||||
|
||||
Grouping states
|
||||
---------------
|
||||
Suppose we have the following transaction, where 15 USD is being exchanged for 10 GBP:
|
||||
|
||||
.. image:: resources/ungrouped-tx.png
|
||||
:scale: 20
|
||||
:align: center
|
||||
|
||||
We can imagine that we would like to verify the USD states and the GBP states separately:
|
||||
|
||||
.. image:: resources/grouped-tx.png
|
||||
:scale: 20
|
||||
:align: center
|
||||
|
||||
``TransactionForContract`` provides a ``groupStates`` method to allow you to group states in this way:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/contracts/TransactionVerification.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 2
|
||||
:end-before: DOCEND 2
|
||||
|
||||
Where ``InOutGroup`` is defined as:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/contracts/TransactionVerification.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 3
|
||||
:end-before: DOCEND 3
|
||||
|
||||
For example, we could group the states in the transaction above by currency (i.e. by ``amount.token``):
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
val groups: List<InOutGroup<Cash.State, Issued<Currency>>> = tx.groupStates(Cash.State::class.java) {
|
||||
it -> it.amount.token
|
||||
}
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
final List<InOutGroup<Cash.State, Issued<Currency>>> groups = tx.groupStates(
|
||||
Cash.State.class,
|
||||
it -> it.getAmount().getToken()
|
||||
);
|
||||
|
||||
This would produce the following InOutGroups:
|
||||
|
||||
.. image:: resources/in-out-groups.png
|
||||
|
||||
We can now verify these groups individually:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
for ((in_, out, key) in groups) {
|
||||
when (key) {
|
||||
is GBP -> {
|
||||
// GBP verification logic.
|
||||
}
|
||||
is USD -> {
|
||||
// USD verification logic.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
for (InOutGroup group : groups) {
|
||||
if (group.getGroupingKey() == USD) {
|
||||
// USD verification logic.
|
||||
} else if (group.getGroupingKey() == GBP) {
|
||||
// GBP verification logic.
|
||||
}
|
||||
}
|
||||
|
||||
Legal prose
|
||||
-----------
|
||||
|
||||
Current, ``legalContractReference`` is simply the SHA-256 hash of a contract:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../finance/src/main/kotlin/net/corda/contracts/asset/Cash.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 2
|
||||
:end-before: DOCEND 2
|
||||
|
||||
In the future, a contract's legal prose will be included as an attachment instead.
|
@ -1,30 +1,8 @@
|
||||
Core types
|
||||
==========
|
||||
API: Core types
|
||||
===============
|
||||
|
||||
Corda provides a large standard library of data types used to represent the :doc:`key-concepts-data-model` previously described.
|
||||
In addition, there are a series of helper libraries which provide date manipulation, maths and cryptography functions.
|
||||
|
||||
State and References
|
||||
--------------------
|
||||
State objects contain mutable data which we would expect to evolve over the lifetime of a contract.
|
||||
|
||||
A reference to a state in the ledger (whether it has been consumed or not) is represented with a ``StateRef`` object.
|
||||
If the state ref has been looked up from storage, you will have a ``StateAndRef`` which is simply a ``StateRef`` plus the data.
|
||||
|
||||
The ``ContractState`` type is an interface that all states must implement. A ``TransactionState`` is a simple
|
||||
container for a ``ContractState`` (the custom data used by a contract program) and additional platform-level state
|
||||
information, such as the *notary* pointer (see :doc:`key-concepts-consensus-notaries`).
|
||||
|
||||
A number of interfaces then extend ``ContractState``, representing standardised functionality for common kinds
|
||||
of state such as:
|
||||
|
||||
``OwnableState``
|
||||
A state which has an owner (represented as a ``PublicKey`` which can be a ``CompositeKey``, discussed later). Exposes the owner and a function
|
||||
for replacing the owner e.g. when an asset is sold.
|
||||
|
||||
``SchedulableState``
|
||||
A state to indicate whether there is some activity to be performed at some future point in time with respect to this
|
||||
contract, what that activity is and at what point in time it should be initiated.
|
||||
Corda provides a large standard library of data types used to represent the Corda data model. In addition, there are a
|
||||
series of helper libraries which provide date manipulation, maths and cryptography functions.
|
||||
|
||||
NamedByHash and UniqueIdentifier
|
||||
--------------------------------
|
||||
@ -38,47 +16,6 @@ This is a combination of a (Java) ``UUID`` representing a globally unique 128 bi
|
||||
string which can be paired with it. For instance the string may represent an existing "weak" (not guaranteed unique)
|
||||
identifier for convenience purposes.
|
||||
|
||||
|
||||
Transaction lifecycle types
|
||||
---------------------------
|
||||
|
||||
A ``WireTransaction`` instance contains the core of a transaction without signatures, and with references to attachments
|
||||
in place of the attachments themselves (see also :doc:`key-concepts-data-model`). Once signed these are encapsulated in a
|
||||
``SignedTransaction`` instance. For processing a transaction (i.e. to verify it) a ``SignedTransaction`` is then converted to a
|
||||
``LedgerTransaction``, which involves verifying the signatures and associating them to the relevant command(s), and
|
||||
resolving the attachment references to the attachments. Commands with valid signatures are encapsulated in the
|
||||
``AuthenticatedObject`` type.
|
||||
|
||||
.. note:: A ``LedgerTransaction`` has not necessarily had its contract code executed, and thus could be contract-invalid
|
||||
(but not signature-invalid). You can use the ``verify`` method as shown below to validate the contracts.
|
||||
|
||||
When constructing a new transaction from scratch, you use ``TransactionBuilder``, which is a mutable transaction that
|
||||
can be signed once its construction is complete. This builder class should be used to create the initial transaction representation
|
||||
(before signature, before verification). It is intended to be passed around code that may edit it by adding new states/commands.
|
||||
Then once the states and commands are right then an initial DigitalSignature.WithKey can be added to freeze the transaction data.
|
||||
Typically, the signInitialTransaction method on the flow's serviceHub object will be used to look up the default node identity PrivateKey,
|
||||
sign the transaction and return a partially signed SignedTransaction. This can then be distributed to other participants using the :doc:`key-concepts-flow-framework`.
|
||||
|
||||
Here's an example of building a transaction that creates an issuance of bananas (note that bananas are not a real
|
||||
contract type in the library):
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
val notaryToUse: Party = ...
|
||||
val txb = TransactionBuilder(notary = notaryToUse).withItems(BananaState(Amount(20, Bananas), fromCountry = "Elbonia"))
|
||||
txb.setTime(Instant.now(), notaryToUse, 30.seconds)
|
||||
// Carry out the initial signing of the transaction and creation of a (partial) SignedTransation.
|
||||
val stx = serviceHub.signInitialTransaction(txb)
|
||||
// Alternatively, let's just check it verifies pretending it was fully signed. To do this, we get
|
||||
// a WireTransaction, which is what the SignedTransaction wraps. Thus by verifying that directly we
|
||||
// skip signature checking.
|
||||
txb.toWireTransaction().toLedgerTransaction(services).verify()
|
||||
|
||||
In a unit test, you would typically use a freshly created ``MockServices`` object, or more realistically, you would
|
||||
write your tests using the :doc:`domain specific language for writing tests <tutorial-test-dsl>`.
|
||||
|
||||
Party and CompositeKey
|
||||
----------------------
|
||||
|
314
docs/source/api-flows.rst
Normal file
@ -0,0 +1,314 @@
|
||||
.. highlight:: kotlin
|
||||
.. raw:: html
|
||||
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/codesets.js"></script>
|
||||
|
||||
API: Flows
|
||||
==========
|
||||
|
||||
.. note:: Before reading this page, you should be familiar with the key concepts of :doc:`key-concepts-flows`.
|
||||
|
||||
An example flow
|
||||
---------------
|
||||
Let's imagine a flow for agreeing a basic ledger update between Alice and Bob. This flow will have two sides:
|
||||
|
||||
* An ``Initiator`` side, that will initiate the request to update the ledger
|
||||
* A ``Responder`` side, that will respond to the request to update the ledger
|
||||
|
||||
Initiator
|
||||
^^^^^^^^^
|
||||
In our flow, the Initiator flow class will be doing the majority of the work:
|
||||
|
||||
*Part 1 - Build the transaction*
|
||||
|
||||
1. Choose a notary for the transaction
|
||||
2. Create a transaction builder
|
||||
3. Extract any input states from the vault and add them to the builder
|
||||
4. Create any output states and add them to the builder
|
||||
5. Add any commands, attachments and timestamps to the builder
|
||||
|
||||
*Part 2 - Sign the transaction*
|
||||
|
||||
6. Sign the transaction builder
|
||||
7. Convert the builder to a signed transaction
|
||||
|
||||
*Part 3 - Verify the transaction*
|
||||
|
||||
8. Verify the transaction by running its contracts
|
||||
|
||||
*Part 4 - Gather the counterparty's signature*
|
||||
|
||||
9. Send the transaction to the counterparty
|
||||
10. Wait to receive back the counterparty's signature
|
||||
11. Add the counterparty's signature to the transaction
|
||||
12. Verify the transaction's signatures
|
||||
|
||||
*Part 5 - Finalize the transaction*
|
||||
|
||||
13. Send the transaction to the notary
|
||||
14. Wait to receive back the notarised transaction
|
||||
15. Record the transaction locally
|
||||
16. Store any relevant states in the vault
|
||||
17. Send the transaction to the counterparty for recording
|
||||
|
||||
We can visualize the work performed by initiator as follows:
|
||||
|
||||
.. image:: resources/flow-overview.png
|
||||
|
||||
Responder
|
||||
^^^^^^^^^
|
||||
To respond to these actions, the responder takes the following steps:
|
||||
|
||||
*Part 1 - Sign the transaction*
|
||||
|
||||
1. Receive the transaction from the counterparty
|
||||
2. Verify the transaction's existing signatures
|
||||
3. Verify the transaction by running its contracts
|
||||
4. Generate a signature over the transaction
|
||||
5. Send the signature back to the counterparty
|
||||
|
||||
*Part 2 - Record the transaction*
|
||||
|
||||
6. Receive the notarised transaction from the counterparty
|
||||
7. Record the transaction locally
|
||||
8. Store any relevant states in the vault
|
||||
|
||||
FlowLogic
|
||||
---------
|
||||
In practice, a flow is implemented as one or more communicating ``FlowLogic`` subclasses. Each ``FlowLogic`` subclass
|
||||
must override ``FlowLogic.call()``, which describes the actions it will take as part of the flow.
|
||||
|
||||
So in the example above, we would have an ``Initiator`` ``FlowLogic`` subclass and a ``Responder`` ``FlowLogic``
|
||||
subclass. The actions of the initiator's side of the flow would be defined in ``Initiator.call``, and the actions
|
||||
of the responder's side of the flow would be defined in ``Responder.call``.
|
||||
|
||||
FlowLogic annotations
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
Any flow that you wish to start either directly via RPC or as a subflow must be annotated with the
|
||||
``@InitiatingFlow`` annotation. Additionally, if you wish to start the flow via RPC, you must annotate it with the
|
||||
``@StartableByRPC`` annotation.
|
||||
|
||||
Any flow that responds to a message from another flow must be annotated with the ``@InitiatedBy`` annotation.
|
||||
``@InitiatedBy`` takes the class of the flow it is responding to as its single parameter.
|
||||
|
||||
So in our example, we would have:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
@InitiatingFlow
|
||||
@StartableByRPC
|
||||
class Initiator(): FlowLogic<Unit>() {
|
||||
|
||||
...
|
||||
|
||||
@InitiatedBy(Initiator::class)
|
||||
class Responder(val otherParty: Party) : FlowLogic<Unit>() {
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
@InitiatingFlow
|
||||
@StartableByRPC
|
||||
public static class Initiator extends FlowLogic<Unit> {
|
||||
|
||||
...
|
||||
|
||||
@InitiatedBy(Initiator.class)
|
||||
public static class Responder extends FlowLogic<Void> {
|
||||
|
||||
Additionally, any flow that is started by a ``SchedulableState`` must be annotated with the ``@SchedulableFlow``
|
||||
annotation.
|
||||
|
||||
ServiceHub
|
||||
----------
|
||||
Within ``FlowLogic.call()``, the flow developer has access to the node's ``ServiceHub`` that provides access to the
|
||||
various services the node provides.
|
||||
|
||||
The key ``ServiceHub`` services are:
|
||||
|
||||
* ``ServiceHub.networkMapCache``
|
||||
* Provides info on other nodes on the network (e.g. notaries…)
|
||||
* ``ServiceHub.vaultService``
|
||||
* Stores the node’s current and historic states
|
||||
* ``ServiceHub.storageService``
|
||||
* Stores additional info such as transactions and attachments
|
||||
* ``ServiceHub.keyManagementService``
|
||||
* Manages the node’s digital signing keys
|
||||
* ``ServiceHub.myInfo``
|
||||
* Other information about the node
|
||||
* ``ServiceHub.clock``
|
||||
* Provides access to the node’s internal time and date
|
||||
|
||||
Some common tasks performed using the ``ServiceHub`` are:
|
||||
|
||||
* Looking up your own identity or the identity of a counterparty using the ``networkMapCache``
|
||||
* Identifying the providers of a given service (e.g. a notary service) using the ``networkMapCache``
|
||||
* Retrieving states to use in a transaction using the ``vaultService``
|
||||
* Retrieving attachments and past transactions to use in a transaction using the ``storageService``
|
||||
* Creating a timestamp using the ``clock``
|
||||
* Signing a transaction using the ``keyManagementService``
|
||||
|
||||
Common flow tasks
|
||||
-----------------
|
||||
There are a number of common tasks that you will need to perform within ``FlowLogic.call`` in order to agree ledger
|
||||
updates. This section details the API for the most common tasks.
|
||||
|
||||
Retrieving information about other nodes
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
We use the network map to retrieve information about other nodes on the network:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
val networkMap = serviceHub.networkMapCache
|
||||
|
||||
val allNodes = networkMap.partyNodes
|
||||
val allNotaryNodes = networkMap.notaryNodes
|
||||
val randomNotaryNode = networkMap.getAnyNotary()
|
||||
|
||||
val alice = networkMap.getNodeByLegalName(X500Name("CN=Alice,O=Alice,L=London,C=UK"))
|
||||
val bob = networkMap.getNodeByLegalIdentityKey(bobsKey)
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
final NetworkMapCache networkMap = getServiceHub().getNetworkMapCache();
|
||||
|
||||
final List<NodeInfo> allNodes = networkMap.getPartyNodes();
|
||||
final List<NodeInfo> allNotaryNodes = networkMap.getNotaryNodes();
|
||||
final Party randomNotaryNode = networkMap.getAnyNotary(null);
|
||||
|
||||
final NodeInfo alice = networkMap.getNodeByLegalName(new X500Name("CN=Alice,O=Alice,L=London,C=UK"));
|
||||
final NodeInfo bob = networkMap.getNodeByLegalIdentityKey(bobsKey);
|
||||
|
||||
Communication between parties
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
``FlowLogic`` instances communicate using three functions:
|
||||
|
||||
* ``send(otherParty: Party, payload: Any)``
|
||||
* Sends the ``payload`` object to the ``otherParty``
|
||||
* ``receive(receiveType: Class<R>, otherParty: Party)``
|
||||
* Receives an object of type ``receiveType`` from the ``otherParty``
|
||||
* ``sendAndReceive(receiveType: Class<R>, otherParty: Party, payload: Any)``
|
||||
* Sends the ``payload`` object to the ``otherParty``, and receives an object of type ``receiveType`` back
|
||||
|
||||
Each ``FlowLogic`` subclass can be annotated to respond to messages from a given *counterparty* flow using the
|
||||
``@InitiatedBy`` annotation. When a node first receives a message from a given ``FlowLogic.call()`` invocation, it
|
||||
responds as follows:
|
||||
|
||||
* The node checks whether they have a ``FlowLogic`` subclass that is registered to respond to the ``FlowLogic`` that
|
||||
is sending the message:
|
||||
|
||||
a. If yes, the node starts an instance of this ``FlowLogic`` by invoking ``FlowLogic.call()``
|
||||
b. Otherwise, the node ignores the message
|
||||
|
||||
* The counterparty steps through their ``FlowLogic.call()`` method until they encounter a call to ``receive()``, at
|
||||
which point they process the message from the initiator
|
||||
|
||||
Upon calling ``receive()``/``sendAndReceive()``, the ``FlowLogic`` is suspended until it receives a response.
|
||||
|
||||
UntrustworthyData
|
||||
~~~~~~~~~~~~~~~~~
|
||||
``send()`` and ``sendAndReceive()`` return a payload wrapped in an ``UntrustworthyData`` instance. This is a
|
||||
reminder that any data received off the wire is untrustworthy and must be verified.
|
||||
|
||||
We verify the ``UntrustworthyData`` and retrieve its payload by calling ``unwrap``:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
val partSignedTx = receive<SignedTransaction>(otherParty).unwrap { partSignedTx ->
|
||||
val wireTx = partSignedTx.verifySignatures(keyPair.public, notaryPubKey)
|
||||
wireTx.toLedgerTransaction(serviceHub).verify()
|
||||
partSignedTx
|
||||
}
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
final SignedTransaction partSignedTx = receive(SignedTransaction.class, otherParty)
|
||||
.unwrap(tx -> {
|
||||
try {
|
||||
final WireTransaction wireTx = tx.verifySignatures(keyPair.getPublic(), notaryPubKey);
|
||||
wireTx.toLedgerTransaction(getServiceHub()).verify();
|
||||
} catch (SignatureException ex) {
|
||||
throw new FlowException(tx.getId() + " failed signature checks", ex);
|
||||
}
|
||||
return tx;
|
||||
});
|
||||
|
||||
Subflows
|
||||
--------
|
||||
Corda provides a number of built-in flows that should be used for handling common tasks. The most important are:
|
||||
|
||||
* ``CollectSignaturesFlow``, which should be used to collect a transaction's required signatures
|
||||
* ``FinalityFlow``, which should be used to notarise and record a transaction
|
||||
* ``ResolveTransactionsFlow``, which should be used to verify the chain of inputs to a transaction
|
||||
* ``ContractUpgradeFlow``, which should be used to change a state's contract
|
||||
* ``NotaryChangeFlow``, which should be used to change a state's notary
|
||||
|
||||
These flows are designed to be used as building blocks in your own flows. You invoke them by calling
|
||||
``FlowLogic.subFlow`` from within your flow's ``call`` method. Here is an example from ``TwoPartyDealFlow.kt``:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/flows/TwoPartyDealFlow.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 1
|
||||
:end-before: DOCEND 1
|
||||
:dedent: 12
|
||||
|
||||
In this example, we are starting a ``CollectSignaturesFlow``, passing in a partially signed transaction, and
|
||||
receiving back a fully-signed version of the same transaction.
|
||||
|
||||
Subflows in our example flow
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
In practice, many of the actions in our example flow would be automated using subflows:
|
||||
|
||||
* Parts 2-4 of ``Initiator.call`` should be automated by invoking ``CollectSignaturesFlow``
|
||||
* Part 5 of ``Initiator.call`` should be automated by invoking ``FinalityFlow``
|
||||
* Part 1 of ``Responder.call`` should be automated by invoking ``SignTransactionFlow``
|
||||
* Part 2 of ``Responder.call`` will be handled automatically when the counterparty invokes ``FinalityFlow``
|
||||
|
||||
FlowException
|
||||
-------------
|
||||
Suppose a node throws an exception while running a flow. Any counterparty flows waiting for a message from the node
|
||||
(i.e. as part of a call to ``receive`` or ``sendAndReceive``) will be notified that the flow has unexpectedly
|
||||
ended and will themselves end. However, the exception thrown will not be propagated back to the counterparties.
|
||||
|
||||
If you wish to notify any waiting counterparties of the cause of the exception, you can do so by throwing a
|
||||
``FlowException``:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/flows/FlowException.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 1
|
||||
:end-before: DOCEND 1
|
||||
|
||||
The flow framework will automatically propagate the ``FlowException`` back to the waiting counterparties.
|
||||
|
||||
There are many scenarios in which throwing a ``FlowException`` would be appropriate:
|
||||
|
||||
* A transaction doesn't ``verify()``
|
||||
* A transaction's signatures are invalid
|
||||
* The transaction does not match the parameters of the deal as discussed
|
||||
* You are reneging on a deal
|
||||
|
||||
Suspending flows
|
||||
----------------
|
||||
In order for nodes to be able to run multiple flows concurrently, and to allow flows to survive node upgrades and
|
||||
restarts, flows need to be checkpointable and serializable to disk.
|
||||
|
||||
This is achieved by marking any function invoked from within ``FlowLogic.call()`` with an ``@Suspendable`` annotation.
|
||||
|
||||
We can see an example in ``CollectSignaturesFlow``:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/flows/CollectSignaturesFlow.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 1
|
||||
:end-before: DOCEND 1
|
147
docs/source/api-states.rst
Normal file
@ -0,0 +1,147 @@
|
||||
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``.
|
||||
|
||||
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.
|
||||
|
||||
* ``withNewOwner(newOwner: PublicKey)`` creates an identical copy of the state, only with a new owner
|
||||
|
||||
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:`persistence`)
|
||||
* ``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/contracts/asset/Cash.kt
|
||||
: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
|
299
docs/source/api-transactions.rst
Normal file
@ -0,0 +1,299 @@
|
||||
.. highlight:: kotlin
|
||||
.. raw:: html
|
||||
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/codesets.js"></script>
|
||||
|
||||
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:
|
||||
|
||||
* ``TransactionBuilder``, a mutable transaction-in-construction
|
||||
* ``WireTransaction``, an immutable transaction
|
||||
* ``SignedTransaction``, a ``WireTransaction`` with 1+ associated signatures
|
||||
* ``LedgerTransaction``, a resolved ``WireTransaction`` that can be checked for contract validity
|
||||
|
||||
Here are the possible transitions between transaction states:
|
||||
|
||||
.. image:: resources/transaction-flow.png
|
||||
|
||||
TransactionBuilder
|
||||
------------------
|
||||
Creating a builder
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
The first step when building a transaction is to create a ``TransactionBuilder``:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
// A general transaction builder.
|
||||
val generalTxBuilder = TransactionType.General.Builder()
|
||||
|
||||
// A notary-change transaction builder.
|
||||
val notaryChangeTxBuilder = TransactionType.NotaryChange.Builder()
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
// A general transaction builder.
|
||||
final TransactionBuilder generalTxBuilder = new TransactionType.General.Builder();
|
||||
|
||||
// A notary-change transaction builder.
|
||||
final TransactionBuilder notaryChangeTxBuilder = new TransactionType.NotaryChange.Builder();
|
||||
|
||||
Adding items
|
||||
^^^^^^^^^^^^
|
||||
The transaction builder is mutable. We add items to it using the ``TransactionBuilder.withItems`` method:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 1
|
||||
:end-before: DOCEND 1
|
||||
|
||||
``withItems`` takes a ``vararg`` of objects and adds them to the builder based on their type:
|
||||
|
||||
* ``StateAndRef`` objects are added as input states
|
||||
* ``TransactionState`` and ``ContractState`` objects are added as output states
|
||||
* ``Command`` objects are added as commands
|
||||
|
||||
Passing in objects of any other type will cause an ``IllegalArgumentException`` to be thrown.
|
||||
|
||||
You can also add the following items to the transaction:
|
||||
|
||||
* ``TimeWindow`` objects, using ``TransactionBuilder.setTime``
|
||||
* ``SecureHash`` objects referencing the hash of an attachment stored on the node, using
|
||||
``TransactionBuilder.addAttachment``
|
||||
|
||||
Input states
|
||||
~~~~~~~~~~~~
|
||||
Input states are added to a transaction as ``StateAndRef`` instances, rather than as ``ContractState`` instances.
|
||||
|
||||
A ``StateAndRef`` combines a ``ContractState`` with a pointer to the transaction that created it. This series of
|
||||
pointers from the input states back to the transactions that created them is what allows a node to work backwards and
|
||||
verify the entirety of the transaction chain. It is defined as:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/contracts/Structures.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 7
|
||||
:end-before: DOCEND 7
|
||||
|
||||
Where ``StateRef`` is defined as:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/contracts/Structures.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 8
|
||||
:end-before: DOCEND 8
|
||||
|
||||
``StateRef.index`` is the state's position in the outputs of the transaction that created it. In this way, a
|
||||
``StateRef`` allows a notary service to uniquely identify the existing states that a transaction is marking as historic.
|
||||
|
||||
Output states
|
||||
~~~~~~~~~~~~~
|
||||
Since a transaction's output states do not exist until the transaction is committed, they cannot be referenced as the
|
||||
outputs of previous transactions. Instead, we create the desired output states as ``ContractState`` instances, and
|
||||
add them to the transaction.
|
||||
|
||||
Commands
|
||||
~~~~~~~~
|
||||
Commands are added to the transaction as ``Command`` instances. ``Command`` combines a ``CommandData``
|
||||
instance representing the type of the command with a list of the command's required signers. It is defined as:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/contracts/Structures.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 9
|
||||
:end-before: DOCEND 9
|
||||
|
||||
Signing the builder
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
Once the builder is ready, we finalize it by signing it and converting it into a ``SignedTransaction``:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
// Finalizes the builder by signing it with our primary signing key.
|
||||
val signedTx1 = serviceHub.signInitialTransaction(unsignedTx)
|
||||
|
||||
// Finalizes the builder by signing it with a different key.
|
||||
val signedTx2 = serviceHub.signInitialTransaction(unsignedTx, otherKey)
|
||||
|
||||
// Finalizes the builder by signing it with a set of keys.
|
||||
val signedTx3 = serviceHub.signInitialTransaction(unsignedTx, otherKeys)
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
// Finalizes the builder by signing it with our primary signing key.
|
||||
final SignedTransaction signedTx1 = getServiceHub().signInitialTransaction(unsignedTx);
|
||||
|
||||
// Finalizes the builder by signing it with a different key.
|
||||
final SignedTransaction signedTx2 = getServiceHub().signInitialTransaction(unsignedTx, otherKey);
|
||||
|
||||
// Finalizes the builder by signing it with a set of keys.
|
||||
final SignedTransaction signedTx3 = getServiceHub().signInitialTransaction(unsignedTx, otherKeys);
|
||||
|
||||
SignedTransaction
|
||||
-----------------
|
||||
A ``SignedTransaction`` is a combination of an immutable ``WireTransaction`` and a list of signatures over that
|
||||
transaction:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/transactions/SignedTransaction.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 1
|
||||
:end-before: DOCEND 1
|
||||
|
||||
Verifying the signatures
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
The signatures on a ``SignedTransaction`` have not necessarily been checked for validity. We check them using
|
||||
``SignedTransaction.verifySignatures``:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/transactions/SignedTransaction.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 2
|
||||
:end-before: DOCEND 2
|
||||
|
||||
``verifySignatures`` takes a ``vararg`` of the public keys for which the signatures are allowed to be missing. If the
|
||||
transaction is missing any signatures without the corresponding public keys being passed in, a
|
||||
``SignaturesMissingException`` is thrown.
|
||||
|
||||
Verifying the transaction
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Verifying a transaction is a multi-step process:
|
||||
|
||||
* We check the transaction's signatures:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
subFlow(ResolveTransactionsFlow(transactionToVerify, partyWithTheFullChain))
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
subFlow(new ResolveTransactionsFlow(transactionToVerify, partyWithTheFullChain));
|
||||
|
||||
* Before verifying the transaction, we need to retrieve from the proposer(s) of the transaction any parts of the
|
||||
transaction chain that our node doesn't currently have in its local storage:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
subFlow(ResolveTransactionsFlow(transactionToVerify, partyWithTheFullChain))
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
subFlow(new ResolveTransactionsFlow(transactionToVerify, partyWithTheFullChain));
|
||||
|
||||
* To verify the transaction, we first need to resolve any state references and attachment hashes by converting the
|
||||
``SignedTransaction`` into a ``LedgerTransaction``. We can then verify the fully-resolved transaction:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
partSignedTx.tx.toLedgerTransaction(serviceHub).verify()
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
partSignedTx.getTx().toLedgerTransaction(getServiceHub()).verify();
|
||||
|
||||
* We will generally also want to conduct some custom validation of the transaction, beyond what is provided for in the
|
||||
contract:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
val ledgerTransaction = partSignedTx.tx.toLedgerTransaction(serviceHub)
|
||||
val inputStateAndRef = ledgerTransaction.inputs.single()
|
||||
val input = inputStateAndRef.state.data as MyState
|
||||
if (input.value > 1000000) {
|
||||
throw FlowException("Proposed input value too high!")
|
||||
}
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
final LedgerTransaction ledgerTransaction = partSignedTx.getTx().toLedgerTransaction(getServiceHub());
|
||||
final StateAndRef inputStateAndRef = ledgerTransaction.getInputs().get(0);
|
||||
final MyState input = (MyState) inputStateAndRef.getState().getData();
|
||||
if (input.getValue() > 1000000) {
|
||||
throw new FlowException("Proposed input value too high!");
|
||||
}
|
||||
|
||||
Signing the transaction
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
We add an additional signature to an existing ``SignedTransaction`` using:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
val fullySignedTx = serviceHub.addSignature(partSignedTx)
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
SignedTransaction fullySignedTx = getServiceHub().addSignature(partSignedTx);
|
||||
|
||||
We can also generate a signature over the transaction without adding it to the transaction directly by using:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
val signature = serviceHub.createSignature(partSignedTx)
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
DigitalSignature.WithKey signature = getServiceHub().createSignature(partSignedTx);
|
||||
|
||||
Notarising and recording
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Notarising and recording a transaction is handled by a built-in flow called ``FinalityFlow``. See
|
||||
:doc:`api-flows` for more details.
|
12
docs/source/api.rst
Normal file
@ -0,0 +1,12 @@
|
||||
API overview
|
||||
============
|
||||
|
||||
This section describes the APIs that are available for the development of CorDapps:
|
||||
|
||||
* :doc:`api-states`
|
||||
* :doc:`api-contracts`
|
||||
* :doc:`api-transactions`
|
||||
* :doc:`api-flows`
|
||||
* :doc:`api-core-types`
|
||||
|
||||
Before reading this page, you should be familiar with the key concepts of Corda: :doc:`key-concepts`.
|
@ -59,7 +59,7 @@ Define the version of Corda you want on your nodes and the type of notary.
|
||||
|
||||
.. image:: resources/azure_multi_node_step3.png
|
||||
:width: 300px
|
||||
|
||||
|
||||
Click 'OK'
|
||||
|
||||
STEP 4: Summary
|
||||
@ -146,7 +146,7 @@ In the browser window type the following URL to send a Yo message to a target no
|
||||
.. sourcecode:: shell
|
||||
|
||||
http://(public IP address):(port)/api/yo/yo?target=(legalname of target node)
|
||||
|
||||
|
||||
where (public IP address) is the public IP address of one of your Corda nodes on the Azure Corda network and (port) is the web server port number for your Corda node, 10004 by default and (legalname of target node) is the Legal Name for the target node as defined in the node.conf file, for example:
|
||||
|
||||
.. sourcecode:: shell
|
||||
@ -197,7 +197,7 @@ You can open log files with any text editor.
|
||||
|
||||
.. image:: resources/azure_syslog.png
|
||||
:width: 300px
|
||||
|
||||
|
||||
Next Steps
|
||||
----------
|
||||
Now you have built a Corda network and used a basic Corda CorDapp do go and visit the `dedicated Corda website <https://www.corda.net>`_
|
||||
|
@ -530,7 +530,7 @@ New features in this release:
|
||||
are trees of public keys in which interior nodes can have validity thresholds attached, thus allowing
|
||||
boolean formulas of keys to be created. This is similar to Bitcoin's multi-sig support and the data model
|
||||
is the same as the InterLedger Crypto-Conditions spec, which should aid interop in future. Read more about
|
||||
key trees in the ":doc:`key-concepts-core-types`" article.
|
||||
key trees in the ":doc:`api-core-types`" article.
|
||||
* A new tutorial has been added showing how to use transaction attachments in more detail.
|
||||
|
||||
* Testnet
|
||||
@ -546,7 +546,7 @@ New features in this release:
|
||||
* Standalone app development:
|
||||
|
||||
* The Corda libraries that app developers need to link against can now be installed into your local Maven
|
||||
repository, where they can then be used like any other JAR. See :doc:`creating-a-cordapp`.
|
||||
repository, where they can then be used like any other JAR. See :doc:`running-a-node`.
|
||||
|
||||
* User interfaces:
|
||||
|
||||
@ -705,8 +705,8 @@ Highlights of this release:
|
||||
We have new documentation on:
|
||||
|
||||
* :doc:`event-scheduling`
|
||||
* :doc:`key-concepts-core-types`
|
||||
* :doc:`key-concepts-consensus-notaries`
|
||||
* :doc:`core-types`
|
||||
* :doc:`key-concepts-consensus`
|
||||
|
||||
Summary of API changes (not exhaustive):
|
||||
|
||||
|
@ -86,7 +86,7 @@ Whitelisting classes with the Corda node
|
||||
To avoid the RPC interface being wide open to all
|
||||
classes on the classpath, Cordapps have to whitelist any classes they require with the serialization framework of Corda,
|
||||
if they are not one of those whitelisted by default in ``DefaultWhitelist``, via either the plugin architecture or simply
|
||||
with the annotation ``@CordaSerializable``. See :doc:`creating-a-cordapp` or :doc:`serialization`. An example is shown in :doc:`tutorial-clientrpc-api`.
|
||||
with the annotation ``@CordaSerializable``. See :doc:`running-a-node` or :doc:`serialization`. An example is shown in :doc:`tutorial-clientrpc-api`.
|
||||
|
||||
.. warning:: We will be replacing the use of Kryo in the serialization framework and so additional changes here are likely.
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/codesets.js"></script>
|
||||
|
||||
Upgrading Contracts
|
||||
Upgrading contracts
|
||||
===================
|
||||
|
||||
While every care is taken in development of contract code,
|
||||
|
@ -1,54 +0,0 @@
|
||||
The Corda plugin framework
|
||||
==========================
|
||||
|
||||
The intention is that Corda is a common platform, which will be extended
|
||||
by numerous application extensions (CorDapps). These extensions will
|
||||
package together all of the Corda contract code, state structures,
|
||||
protocols/flows to create and modify state as well as RPC extensions for
|
||||
node clients. Details of writing these CorDapps is given elsewhere
|
||||
:doc:`creating-a-cordapp`.
|
||||
|
||||
To enable these plugins to register dynamically with the Corda framework
|
||||
the node uses the Java ``ServiceLoader`` to locate and load the plugin
|
||||
components during the ``AbstractNode.start`` call. Therefore,
|
||||
to be recognised as a plugin the component must:
|
||||
|
||||
1. Include a default constructable class extending from
|
||||
``net.corda.core.node.CordaPluginRegistry`` which overrides the relevant
|
||||
registration methods.
|
||||
|
||||
2. Include a resource file named
|
||||
``net.corda.core.node.CordaPluginRegistry`` in the ``META-INF.services``
|
||||
path. This must include a line containing the fully qualified name of
|
||||
the ``CordaPluginRegistry`` implementation class. Multiple plugin
|
||||
registries are allowed in this file if desired.
|
||||
|
||||
3. The plugin component must be on the classpath. In the normal use this
|
||||
means that it should be present within the plugins subfolder of the
|
||||
node's workspace.
|
||||
|
||||
4. As a plugin the registered components are then allowed access to some
|
||||
of the node internal subsystems.
|
||||
|
||||
5. The overridden properties on the registry class information about the different
|
||||
extensions to be created, or registered at startup. In particular:
|
||||
|
||||
a. The ``webApis`` property is a list of JAX-RS annotated REST access
|
||||
classes. These classes will be constructed by the bundled web server
|
||||
and must have a single argument constructor taking a ``CordaRPCOps``
|
||||
reference. This will allow it to communicate with the node process
|
||||
via the RPC interface. These web APIs will not be available if the
|
||||
bundled web server is not started.
|
||||
|
||||
b. The ``staticServeDirs`` property maps static web content to virtual
|
||||
paths and allows simple web demos to be distributed within the CorDapp
|
||||
jars. These static serving directories will not be available if the
|
||||
bundled web server is not started.
|
||||
|
||||
c. The ``customizeSerialization`` function allows classes to be whitelisted
|
||||
for object serialisation, over and above those tagged with the ``@CordaSerializable``
|
||||
annotation. In general the annotation should be preferred. For
|
||||
instance new state types will need to be explicitly registered. This will be called at
|
||||
various points on various threads and needs to be stable and thread safe. See
|
||||
:doc:`serialization`.
|
||||
|
30
docs/source/corda-repo-layout.rst
Normal file
@ -0,0 +1,30 @@
|
||||
Corda repo layout
|
||||
=================
|
||||
|
||||
The Corda repository comprises the following folders:
|
||||
|
||||
* **buildSrc** contains necessary gradle plugins to build Corda
|
||||
* **client** contains libraries for connecting to a node, working with it remotely and binding server-side data to
|
||||
JavaFX UI
|
||||
* **config** contains logging configurations and the default node configuration file
|
||||
* **cordform-common** contains utilities related to building and running nodes
|
||||
* **core** containing the core Corda libraries such as crypto functions, types for Corda's building blocks: states,
|
||||
contracts, transactions, attachments, etc. and some interfaces for nodes and protocols
|
||||
* **docs** contains the Corda docsite in restructured text format as well as the built docs in html. The docs can be
|
||||
accessed via ``/docs/index.html`` from the root of the repo
|
||||
* **experimental** contains platform improvements that are still in the experimental stage
|
||||
* **finance** defines a range of elementary contracts (and associated schemas) and protocols, such as abstract fungible
|
||||
assets, cash, obligation and commercial paper
|
||||
* **gradle** contains the gradle wrapper which you'll use to execute gradle commands
|
||||
* **gradle-plugins** contains some additional plugins which we use to deploy Corda nodes
|
||||
* **lib** contains some dependencies
|
||||
* **node** contains the core code of the Corda node (eg: node driver, node services, messaging, persistence)
|
||||
* **node-api** contains data structures shared between the node and the client module, e.g. types sent via RPC
|
||||
* **node-schemas** contains entity classes used to represent relational database tables
|
||||
* **samples** contains all our Corda demos and code samples
|
||||
* **test-utils** contains some utilities for unit testing contracts ( the contracts testing DSL) and protocols (the
|
||||
mock network) implementation
|
||||
* **tools** contains the explorer which is a GUI front-end for Corda, and also the DemoBench which is a GUI tool that
|
||||
allows you to run Corda nodes locally for demonstrations
|
||||
* **verifier** allows out-of-node transaction verification, allowing verification to scale horizontally
|
||||
* **webserver** is a servlet container for CorDapps that export HTTP endpoints. This server is an RPC client of the node
|
26
docs/source/cordapp-overview.rst
Normal file
@ -0,0 +1,26 @@
|
||||
CorDapp overview
|
||||
================
|
||||
|
||||
Corda is a platform. Its functionality is extended by developers through the writing of Corda distributed
|
||||
applications (CorDapps). CorDapps are installed at the level of the individual node, rather than on the network
|
||||
itself.
|
||||
|
||||
Each CorDapp allows a node to handle new business processes - everything from asset trading (see :ref:`irs-demo`) to
|
||||
portfolio valuations (see :ref:`simm-demo`). It does so by defining new flows on the node that, once started by the
|
||||
node owner, conduct the process of negotiating a specific ledger update with other nodes on the network. The node's
|
||||
owner can then start these flows as required, either through remote procedure calls (RPC) or HTTP requests that
|
||||
leverage the RPC interface.
|
||||
|
||||
.. image:: resources/node-diagram.png
|
||||
|
||||
CorDapp developers will usually define not only these flows, but also any states and contracts that these flows use.
|
||||
They will also have to define any web APIs that will run on the node's standalone web server, any static web content,
|
||||
and any new services that they want their CorDapp to offer.
|
||||
|
||||
CorDapps are made up of definitions for the following components:
|
||||
|
||||
* States
|
||||
* Contracts
|
||||
* Flows
|
||||
* Web APIs and static web content
|
||||
* Services
|
4
docs/source/faq.rst
Normal file
@ -0,0 +1,4 @@
|
||||
Frequently asked questions
|
||||
==========================
|
||||
|
||||
A list of frequently asked questions can be found on our `forum <https://discourse.corda.net/c/faq>`_.
|
@ -1,4 +1,4 @@
|
||||
Flow Library
|
||||
Flow library
|
||||
============
|
||||
|
||||
There are a number of built-in flows supplied with Corda, which cover some core functionality.
|
||||
|
@ -156,7 +156,7 @@ simply flow messages or exceptions. The other two represent the buyer and seller
|
||||
Going through the data needed to become a seller, we have:
|
||||
|
||||
- ``otherParty: Party`` - the party with which you are trading.
|
||||
- ``notaryNode: NodeInfo`` - the entry in the network map for the chosen notary. See ":doc:`key-concepts-consensus-notaries`" for more
|
||||
- ``notaryNode: NodeInfo`` - the entry in the network map for the chosen notary. See ":doc:`key-concepts-notaries`" for more
|
||||
information on notaries.
|
||||
- ``assetToSell: StateAndRef<OwnableState>`` - a pointer to the ledger entry that represents the thing being sold.
|
||||
- ``price: Amount<Currency>`` - the agreed on price that the asset is being sold for (without an issuer constraint).
|
||||
|
@ -1,14 +0,0 @@
|
||||
Further notes on Kotlin
|
||||
-----------------------
|
||||
|
||||
Corda is written in a language called `Kotlin <https://kotlinlang.org/>`_. Kotlin is a language that targets the JVM
|
||||
and can be thought of as a simpler Scala, with much better Java interop. It is developed by and has commercial support
|
||||
from JetBrains, the makers of the IntelliJ IDE and other popular developer tools.
|
||||
|
||||
Kotlin is a relatively new language and is extremely easy to learn. It is designed as a better Java for industrial
|
||||
use and, as such, the syntax was carefully designed to be readable even to people who don't know the language, after only
|
||||
a few minutes of introduction. Additionally, at R3, we find that all of our developers are up to productive writing speed
|
||||
in Kotlin within their first week.
|
||||
|
||||
Due to the seamless Java interop the use of Kotlin to extend the platform is *not* required and the tutorial shows how
|
||||
to write contracts in both Kotlin and Java. You can `read more about why Kotlin is a potentially strong successor to Java here <https://medium.com/@octskyward/why-kotlin-is-my-next-programming-language-c25c001e26e3>`_.
|
@ -3,54 +3,49 @@ Getting set up
|
||||
|
||||
Software requirements
|
||||
---------------------
|
||||
Corda uses industry-standard tools:
|
||||
|
||||
Corda uses industry-standard tools to make set-up as simple as possible. Following the software recommendations below will minimize the number of errors you encounter, and make it easier for others to provide support. However, if you do use other tools, we'd be interested to hear about any issues that arise.
|
||||
* **Oracle JDK 8 JVM** - supported version **8u131**
|
||||
* **IntelliJ IDEA** - supported versions **2017.1**, **2017.2** and **2017.3**
|
||||
* **Gradle** - supported version **3.4**
|
||||
* **Kotlin** - supported version **1.1.2**
|
||||
* **Git**
|
||||
|
||||
JVM
|
||||
~~~
|
||||
You do not need to install Gradle or Kotlin. A standalone Gradle wrapper is provided, and it will download the correct
|
||||
version of Kotlin.
|
||||
|
||||
Corda is written in Kotlin and runs in a JVM. We develop against Oracle JDK 8, and other JVM implementations are not actively supported.
|
||||
Please note:
|
||||
|
||||
Please ensure that you keep your Oracle JDK installation updated to the latest version while working with Corda. Even earlier versions of JDK 8 versions can cause cryptic errors.
|
||||
* Corda runs in a JVM. JVM implementations other than Oracle JDK 8 are not actively supported. However, if you do
|
||||
choose to use OpenJDK, you will also need to install OpenJFX
|
||||
|
||||
If you do choose to use OpenJDK instead of Oracle's JDK, you will also need to install OpenJFX.
|
||||
* Applications on Corda (CorDapps) can be written in any language targeting the JVM. However, Corda itself and most of
|
||||
the samples are written in Kotlin. Kotlin is an
|
||||
`official Android language <https://developer.android.com/kotlin/index.html>`_, and you can read more about why
|
||||
Kotlin is a strong successor to Java
|
||||
`here <https://medium.com/@octskyward/why-kotlin-is-my-next-programming-language-c25c001e26e3>`_. If you're
|
||||
unfamiliar with Kotlin, there is an official
|
||||
`getting started guide <https://kotlinlang.org/docs/tutorials/>`_, and a series of
|
||||
`Kotlin Koans <https://kotlinlang.org/docs/tutorials/koans.html>`_.
|
||||
|
||||
Kotlin
|
||||
~~~~~~
|
||||
* IntelliJ IDEA is recommended due to the strength of its Kotlin integration.
|
||||
|
||||
Applications on Corda (CorDapps) can be written in any JVM-targeting language. However, Corda itself and most of the samples are written in Kotlin. If you're unfamiliar with Kotlin, there is an official `getting started guide <https://kotlinlang.org/docs/tutorials/>`_.
|
||||
|
||||
See also our :doc:`further-notes-on-kotlin`.
|
||||
|
||||
IDE
|
||||
~~~
|
||||
|
||||
We strongly recommend the use of IntelliJ IDEA as an IDE, primarily due to the strength of its Kotlin integration.
|
||||
|
||||
Please make sure that you're running the latest version of IDEA, as older versions have been known to have problems integrating with Gradle, the build tool used by Corda.
|
||||
|
||||
Git
|
||||
~~~
|
||||
|
||||
We use git to version-control Corda.
|
||||
|
||||
Gradle
|
||||
~~~~~~
|
||||
|
||||
We use Gradle as the build tool for Corda. However, you do not need to install Gradle itself, as a wrapper is provided.
|
||||
Following these software recommendations will minimize the number of errors you encounter, and make it easier for
|
||||
others to provide support. However, if you do use other tools, we'd be interested to hear about any issues that arise.
|
||||
|
||||
Set-up instructions
|
||||
-------------------
|
||||
|
||||
The instructions below will allow you to set up a Corda development environment and run a basic CorDapp on a Windows or Mac machine. If you have any issues, please consult the :doc:`getting-set-up-fault-finding` page, or reach out on `Slack <http://slack.corda.net/>`_ or the `forums <https://discourse.corda.net/>`_.
|
||||
The instructions below will allow you to set up a Corda development environment and run a basic CorDapp on a Windows
|
||||
or Mac machine. If you have any issues, please consult the :doc:`troubleshooting` page, or reach out on
|
||||
`Slack <http://slack.corda.net/>`_ or the `forums <https://discourse.corda.net/>`_.
|
||||
|
||||
.. note:: The set-up instructions are also available in video form for both `Windows <https://vimeo.com/217462250>`_ and `Mac <https://vimeo.com/217462230>`_.
|
||||
|
||||
Windows
|
||||
~~~~~~~
|
||||
^^^^^^^
|
||||
|
||||
Java
|
||||
""""
|
||||
~~~~
|
||||
1. Visit http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
|
||||
2. Scroll down to "Java SE Development Kit 8uXXX" (where "XXX" is the latest minor version number)
|
||||
3. Toggle "Accept License Agreement"
|
||||
@ -59,19 +54,19 @@ Java
|
||||
6. Open a new command prompt and run ``java -version`` to test that Java is installed correctly
|
||||
|
||||
Git
|
||||
"""
|
||||
~~~
|
||||
1. Visit https://git-scm.com/download/win
|
||||
2. Click the "64-bit Git for Windows Setup" download link.
|
||||
3. Download and run the executable to install Git (use the default settings)
|
||||
4. Open a new command prompt and type ``git --version`` to test that git is installed correctly
|
||||
|
||||
IntelliJ
|
||||
""""""""
|
||||
~~~~~~~~
|
||||
1. Visit https://www.jetbrains.com/idea/download/download-thanks.html?code=IIC
|
||||
2. Download and run the executable to install IntelliJ Community Edition (use the default settings)
|
||||
|
||||
Download a sample project
|
||||
"""""""""""""""""""""""""
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
1. Open a command prompt
|
||||
2. Clone the CorDapp tutorial repo by running ``git clone https://github.com/corda/cordapp-tutorial``
|
||||
3. Move into the cordapp-tutorial folder by running ``cd cordapp-tutorial``
|
||||
@ -79,14 +74,14 @@ Download a sample project
|
||||
5. Check out the latest milestone release by running ``git checkout release-MX`` (where "X" is the latest milestone)
|
||||
|
||||
Run from the command prompt
|
||||
"""""""""""""""""""""""""""
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
1. From the cordapp-tutorial folder, deploy the nodes by running ``gradlew deployNodes``
|
||||
2. Start the nodes by running ``call kotlin-source/build/nodes/runnodes.bat``
|
||||
3. Wait until all the terminal windows display either "Webserver started up in XX.X sec" or "Node for "NodeC" started up and registered in XX.XX sec"
|
||||
4. Test the CorDapp is running correctly by visiting the front end at http://localhost:10007/web/example/
|
||||
|
||||
Run from IntelliJ
|
||||
"""""""""""""""""
|
||||
~~~~~~~~~~~~~~~~~
|
||||
1. Open IntelliJ Community Edition
|
||||
2. On the splash screen, click "Open" (do NOT click "Import Project") and select the cordapp-template folder
|
||||
|
||||
@ -100,10 +95,10 @@ Run from IntelliJ
|
||||
8. Test the CorDapp is running correctly by visiting the front end at http://localhost:10007/web/example/
|
||||
|
||||
Mac
|
||||
~~~
|
||||
^^^
|
||||
|
||||
Java
|
||||
""""
|
||||
~~~~
|
||||
1. Open "System Preferences > Java"
|
||||
2. In the Java Control Panel, if an update is available, click "Update Now"
|
||||
3. In the "Software Update" window, click "Install Update". If required, enter your password and click "Install Helper" when prompted
|
||||
@ -111,12 +106,12 @@ Java
|
||||
5. Open a new terminal and type ``java -version`` to test that Java is installed correctly
|
||||
|
||||
IntelliJ
|
||||
""""""""
|
||||
~~~~~~~~
|
||||
1. Visit https://www.jetbrains.com/idea/download/download-thanks.html?platform=mac&code=IIC
|
||||
2. Download and run the executable to install IntelliJ Community Edition (use the default settings)
|
||||
|
||||
Download a sample project
|
||||
"""""""""""""""""""""""""
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
1. Open a terminal
|
||||
2. Clone the CorDapp tutorial repo by running ``git clone https://github.com/corda/cordapp-tutorial``
|
||||
3. Move into the cordapp-tutorial folder by running ``cd cordapp-tutorial``
|
||||
@ -124,14 +119,14 @@ Download a sample project
|
||||
5. Check out the latest milestone release by running ``git checkout release-MX`` (where "X" is the latest milestone)
|
||||
|
||||
Run from the terminal
|
||||
"""""""""""""""""""""
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
1. From the cordapp-tutorial folder, deploy the nodes by running ``./gradlew deployNodes``
|
||||
2. Start the nodes by running ``kotlin-source/build/nodes/runnodes``. Do not click while 8 additional terminal windows start up.
|
||||
3. Wait until all the terminal windows display either "Webserver started up in XX.X sec" or "Node for "NodeC" started up and registered in XX.XX sec"
|
||||
4. Test the CorDapp is running correctly by visiting the front end at http://localhost:10007/web/example/
|
||||
|
||||
Run from IntelliJ
|
||||
"""""""""""""""""
|
||||
~~~~~~~~~~~~~~~~~
|
||||
1. Open IntelliJ Community Edition
|
||||
2. On the splash screen, click "Open" (do NOT click "Import Project") and select the cordapp-template folder
|
||||
3. Once the project is open, click "File > Project Structure". Under "Project SDK:", set the project SDK by clicking "New...", clicking "JDK", and navigating to /Library/Java/JavaVirtualMachines/jdk1.8.0_XXX (where "XXX" is the latest minor version number). Click "OK".
|
||||
@ -158,7 +153,8 @@ And a simple example CorDapp for you to explore basic concepts is available here
|
||||
|
||||
You can clone these repos to your local machine by running the command ``git clone [repo URL]``.
|
||||
|
||||
By default, these repos will be on the unstable ``master`` branch. You should check out the latest milestone release instead by running ``git checkout release-M11.1``.
|
||||
By default, these repos will be on the unstable ``master`` branch. You should check out the latest milestone release
|
||||
instead by running ``git checkout release-M11.1``.
|
||||
|
||||
Next steps
|
||||
----------
|
||||
@ -168,5 +164,5 @@ The best way to check that everything is working fine is by :doc:`running-the-de
|
||||
Once you have these demos running, you may be interested in writing your own CorDapps, in which case you should refer to
|
||||
:doc:`tutorial-cordapp`.
|
||||
|
||||
If you encounter any issues, please see the :doc:`getting-set-up-fault-finding` page, or get in touch with us on the
|
||||
If you encounter any issues, please see the :doc:`troubleshooting` page, or get in touch with us on the
|
||||
`forums <https://discourse.corda.net/>`_ or via `slack <http://slack.corda.net/>`_.
|
||||
|
@ -38,56 +38,67 @@ Documentation Contents:
|
||||
=======================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Getting started
|
||||
:maxdepth: 1
|
||||
:caption: Quickstart
|
||||
|
||||
inthebox
|
||||
getting-set-up
|
||||
getting-set-up-fault-finding
|
||||
tutorial-cordapp
|
||||
running-the-demos
|
||||
CLI-vs-IDE
|
||||
cheat-sheet
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
:caption: Key concepts
|
||||
|
||||
key-concepts
|
||||
key-concepts-ecosystem
|
||||
key-concepts-data-model
|
||||
key-concepts-core-types
|
||||
key-concepts-financial-model
|
||||
key-concepts-flow-framework
|
||||
key-concepts-consensus-notaries
|
||||
key-concepts-vault
|
||||
key-concepts-security-model
|
||||
key-concepts-ledger
|
||||
key-concepts-states
|
||||
key-concepts-contracts
|
||||
key-concepts-transactions
|
||||
key-concepts-flows
|
||||
key-concepts-consensus
|
||||
key-concepts-notaries
|
||||
key-concepts-time-windows
|
||||
key-concepts-oracles
|
||||
key-concepts-node
|
||||
key-concepts-tradeoffs
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: CorDapps
|
||||
:maxdepth: 1
|
||||
:caption: Building a CorDapp
|
||||
|
||||
creating-a-cordapp
|
||||
tutorial-cordapp
|
||||
cordapp-overview
|
||||
writing-cordapps
|
||||
api
|
||||
api-states
|
||||
api-contracts
|
||||
api-transactions
|
||||
api-flows
|
||||
api-core-types
|
||||
cheat-sheet
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: The Corda node
|
||||
:maxdepth: 1
|
||||
:caption: Corda nodes
|
||||
|
||||
versioning
|
||||
shell
|
||||
serialization
|
||||
running-a-node
|
||||
clientrpc
|
||||
messaging
|
||||
persistence
|
||||
shell
|
||||
node-administration
|
||||
corda-configuration-file
|
||||
corda-plugins
|
||||
node-services
|
||||
node-explorer
|
||||
permissioning
|
||||
out-of-process-verification
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
:caption: Corda networks
|
||||
|
||||
setting-up-a-corda-network
|
||||
permissioning
|
||||
versioning
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Tutorials
|
||||
|
||||
tutorial-contract
|
||||
@ -106,42 +117,69 @@ Documentation Contents:
|
||||
event-scheduling
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Other
|
||||
:maxdepth: 1
|
||||
:caption: Tools
|
||||
|
||||
network-simulator
|
||||
clauses
|
||||
merkle-trees
|
||||
json
|
||||
demobench
|
||||
node-explorer
|
||||
azure-vm
|
||||
loadtesting
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
:caption: Node internals
|
||||
|
||||
node-services
|
||||
vault
|
||||
serialization
|
||||
messaging
|
||||
persistence
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Component library
|
||||
|
||||
flow-library
|
||||
contract-catalogue
|
||||
financial-model
|
||||
contract-irs
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Appendix
|
||||
:maxdepth: 1
|
||||
:caption: Release process
|
||||
|
||||
loadtesting
|
||||
demobench
|
||||
setting-up-a-corda-network
|
||||
secure-coding-guidelines
|
||||
release-process
|
||||
release-notes
|
||||
changelog
|
||||
codestyle
|
||||
building-the-docs
|
||||
further-notes-on-kotlin
|
||||
publishing-corda
|
||||
azure-vm
|
||||
out-of-process-verification
|
||||
codestyle
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
:caption: FAQ
|
||||
|
||||
faq
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Troubleshooting
|
||||
|
||||
troubleshooting
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Other
|
||||
|
||||
clauses
|
||||
merkle-trees
|
||||
json
|
||||
secure-coding-guidelines
|
||||
corda-repo-layout
|
||||
building-the-docs
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Glossary
|
||||
|
||||
glossary
|
||||
|
@ -1,53 +0,0 @@
|
||||
What's included?
|
||||
================
|
||||
|
||||
This Corda early access preview includes:
|
||||
|
||||
* A collection of samples, for instance a web app demo that uses it to implement IRS trading.
|
||||
* A template app you can use to get started, and tutorial app that teaches you the basics.
|
||||
* A peer to peer network with message persistence and delivery retries.
|
||||
* Key data structures for defining contracts and states.
|
||||
* Smart contracts, which you can find in the :doc:`contract-catalogue`.
|
||||
* API documentation and tutorials (what you're reading).
|
||||
* A business process workflow framework.
|
||||
* Notary infrastructure for precise timestamping, and elimination of double spending without a blockchain.
|
||||
* A simple RPC API.
|
||||
* A user interface for administration.
|
||||
|
||||
Some things it does not currently include but should gain later are:
|
||||
|
||||
* Sandboxing, distribution and publication of smart contract code.
|
||||
* A well specified wire protocol.
|
||||
* An identity framework.
|
||||
|
||||
The open source version of Corda is designed for developers exploring how to write apps. It is not intended to
|
||||
be production grade software. For example it uses an embedded SQL database and doesn't yet have connectivity
|
||||
support for mainstream SQL vendors (Oracle, Postgres, MySQL, SQL Server etc). It hasn't been security audited
|
||||
and the APIs change in every release.
|
||||
|
||||
Source tree layout
|
||||
------------------
|
||||
|
||||
The Corda repository comprises the following folders:
|
||||
|
||||
* **buildSrc** contains necessary gradle plugins to build Corda.
|
||||
* **client** contains libraries for connecting to a node, working with it remotely and binding server-side data to JavaFX UI.
|
||||
* **config** contains logging configurations and the default node configuration file.
|
||||
* **core** containing the core Corda libraries such as crypto functions, types for Corda's building blocks: states,
|
||||
contracts, transactions, attachments, etc. and some interfaces for nodes and protocols.
|
||||
* **docs** contains the Corda docsite in restructured text format as well as the built docs in html. The docs can be
|
||||
accessed via ``/docs/index.html`` from the root of the repo.
|
||||
* **finance** defines a range of elementary contracts (and associated schemas) and protocols, such as abstract fungible
|
||||
assets, cash, obligation and commercial paper.
|
||||
* **gradle** contains the gradle wrapper which you'll use to execute gradle commands.
|
||||
* **gradle-plugins** contains some additional plugins which we use to deploy Corda nodes.
|
||||
* **lib** contains some dependencies.
|
||||
* **node** contains the core code of the Corda node (eg: node driver, node services, messaging, persistence).
|
||||
* **node-api** contains data structures shared between the node and the client module, e.g. types sent via RPC.
|
||||
* **node-schemas** contains entity classes used to represent relational database tables.
|
||||
* **samples** contains all our Corda demos and code samples.
|
||||
* **test-utils** contains some utilities for unit testing contracts ( the contracts testing DSL) and protocols (the
|
||||
mock network) implementation.
|
||||
* **tools** contains the explorer which is a GUI front-end for Corda, and also the DemoBench which is a GUI tool that allows you to run Corda nodes locally for demonstrations.
|
||||
* **verifier** allows out-of-node transaction verification, allowing verification to scale horizontally.
|
||||
* **webserver** is a servlet container for CorDapps that export HTTP endpoints. This server is an RPC client of the node.
|
@ -1,162 +0,0 @@
|
||||
Consensus and notaries
|
||||
======================
|
||||
|
||||
A notary is a service that provides transaction ordering and timestamping.
|
||||
|
||||
Notaries are expected to be composed of multiple mutually distrusting parties who use a standard consensus algorithm.
|
||||
Notaries are identified by and sign with :ref:`composite-keys`. Notaries accept transactions submitted to them for processing
|
||||
and either return a signature over the transaction, or a rejection error that states that a double spend attempt has occurred.
|
||||
|
||||
Corda has "pluggable" notary services to improve privacy, scalability, legal-system compatibility and algorithmic agility.
|
||||
The platform currently provides validating and non-validating notaries, and a distributed RAFT implementation.
|
||||
|
||||
Consensus model
|
||||
---------------
|
||||
|
||||
The fundamental unit of consensus in Corda is the **state**. Consensus can be divided into two parts:
|
||||
|
||||
1. Consensus over state **validity** -- parties can reach certainty that a transaction is accepted by the contracts pointed
|
||||
to by the input and output states, and has all the required signatures. This is achieved by parties independently running
|
||||
the same contract code and validation logic (as described in :doc:`data model <key-concepts-data-model>`)
|
||||
|
||||
2. Consensus over state **uniqueness** -- parties can reach certainty the output states created in a transaction are the
|
||||
unique successors to the input states consumed by that transaction (in other words -- an input state has not been previously
|
||||
consumed)
|
||||
|
||||
.. note:: The current model is still a **work in progress** and everything described in this article can and is likely to change
|
||||
|
||||
Notary
|
||||
------
|
||||
|
||||
A **notary** is an authority responsible for attesting that for a given transaction, it has not signed another transaction
|
||||
consuming any of the same input states. Every **state** has an appointed notary:
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
/**
|
||||
* A wrapper for [ContractState] containing additional platform-level state information.
|
||||
* This is the definitive state that is stored on the ledger and used in transaction outputs
|
||||
*/
|
||||
data class TransactionState<out T : ContractState>(
|
||||
/** The custom contract state */
|
||||
val data: T,
|
||||
/** Identity of the notary that ensures the state is not used as an input to a transaction more than once */
|
||||
val notary: Party) {
|
||||
...
|
||||
}
|
||||
|
||||
Transactions are signed by a notary to ensure their input states are **valid** (apart from *issue* transactions, containing no input states).
|
||||
Furthermore, when using a validating notary, a transaction is only valid if all its dependencies are also valid.
|
||||
|
||||
.. note:: The notary is a logical concept and can itself be a distributed entity, potentially a cluster maintained by mutually distrusting parties
|
||||
|
||||
When the notary is requested to sign a transaction, it either signs it, attesting that the outputs are the **unique**
|
||||
successors of the inputs, or provides conflict information for any input state that has been consumed by another transaction
|
||||
it has already signed. In doing so, the notary provides the point of finality in the system. Until the notary signature
|
||||
is obtained, parties cannot be sure that an equally valid, but conflicting, transaction will not be regarded as confirmed.
|
||||
After the signature is obtained, the parties know that the inputs to this transaction have been uniquely consumed by this transaction.
|
||||
Hence, it is the point at which we can say finality has occurred.
|
||||
|
||||
Multiple notaries
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
More than one notary can exist in a network. This gives the following benefits:
|
||||
|
||||
* **Custom behaviour**. We can have both validating and privacy preserving Notaries -- parties can make a choice based
|
||||
on their specific requirements.
|
||||
* **Load balancing**. Spreading the transaction load over multiple notaries will allow higher transaction throughput in
|
||||
the platform overall
|
||||
* **Low latency**. Latency could be minimised by choosing a notary physically closer the transacting parties
|
||||
|
||||
Changing notaries
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
A transaction should only be signed by a notary if all of its input states point to the same notary.
|
||||
In cases where a transaction involves states controlled by multiple notaries, the states first have to be repointed to the same notary.
|
||||
This is achieved by using a special type of transaction whose sole output state is identical to its sole input state except for its designated notary.
|
||||
Ensuring that all input states point to the same notary is the responsibility of each involved party
|
||||
(it is another condition for an output state of the transaction to be **valid**)
|
||||
|
||||
To change the notary for an input state, use the ``NotaryChangeFlow``. For example:
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
@Suspendable
|
||||
fun changeNotary(originalState: StateAndRef<ContractState>,
|
||||
newNotary: Party): StateAndRef<ContractState> {
|
||||
val flow = NotaryChangeFlow(originalState, newNotary)
|
||||
return subFlow(flow)
|
||||
}
|
||||
|
||||
The flow will:
|
||||
|
||||
1. Construct a transaction with the old state as the input and the new state as the output
|
||||
|
||||
2. Obtain signatures from all *participants* (a participant is any party that is able to consume this state in a valid transaction, as defined by the state itself)
|
||||
|
||||
3. Obtain the *old* notary signature
|
||||
|
||||
4. Record and distribute the final transaction to the participants so that everyone possesses the new state
|
||||
|
||||
.. note:: Eventually, changing notaries will be handled automatically on demand.
|
||||
|
||||
Validation
|
||||
----------
|
||||
|
||||
One of the design decisions for a notary is whether or not to **validate** a transaction before accepting it.
|
||||
|
||||
If a transaction is not checked for validity, it opens the platform to "denial of state" attacks, where anyone can build
|
||||
an invalid transaction consuming someone else's states and submit it to the notary to get the states blocked. However,
|
||||
if the transaction is validated, this requires the notary to be able to see the full contents of the transaction in
|
||||
question and its dependencies. This is an obvious privacy leak.
|
||||
|
||||
The platform is flexible and currently supports both validating and non-validating notary implementations -- a
|
||||
party can select which one to use based on its own privacy requirements.
|
||||
|
||||
.. note:: In the non-validating model, the "denial of state" attack is partially alleviated by requiring the calling
|
||||
party to authenticate and storing its identity for the request. The conflict information returned by the notary
|
||||
specifies the consuming transaction ID along with the identity of the party that had created the transaction. If the
|
||||
conflicting transaction is valid, the current one is aborted; if not, a dispute can be raised and the input states
|
||||
of the conflicting invalid transaction are "un-committed" (via a legal process).
|
||||
|
||||
Timestamping
|
||||
------------
|
||||
|
||||
A notary can also act as a *timestamping authority*, verifying the transaction timestamp command.
|
||||
|
||||
For a timestamp to be meaningful, its implications must be binding on the party requesting it.
|
||||
A party can obtain a timestamp signature in order to prove that some event happened *before*, *on*, or *after* a particular point in time.
|
||||
However, if the party is not also compelled to commit to the associated transaction, it has a choice of whether or not to reveal this fact until some point in the future.
|
||||
As a result, we need to ensure that the notary either has to also sign the transaction within some time tolerance,
|
||||
or perform timestamping *and* notarisation at the same time, which is the chosen behaviour for this model.
|
||||
|
||||
There will never be exact clock synchronisation between the party creating the transaction and the notary.
|
||||
This is not only due to physics, network latencies, etc. but also because between inserting the command and getting the
|
||||
notary to sign there may be many other steps, like sending the transaction to other parties involved in the trade, or
|
||||
even requesting human sign-off. Thus the time observed by the notary may be quite different to the time observed by the
|
||||
party creating the transaction.
|
||||
|
||||
For this reason, times in transactions are specified as time *windows*, not absolute times.
|
||||
In a distributed system there can never be "true time", only an approximation of it. Time windows can be
|
||||
open-ended (i.e. specify only one of "before" and "after") or they can be fully bounded. If a time window needs to
|
||||
be converted to an absolute time (e.g. for display purposes), there is a utility method on ``Timestamp`` to
|
||||
calculate the mid point.
|
||||
|
||||
In this way, we express the idea that the *true value* of the fact "the current time" is actually unknowable. Even when both before and
|
||||
after times are included, the transaction could have occurred at any point between those two timestamps. Here,
|
||||
"occurrence" could mean the execution date, the value date, the trade date etc ... The notary doesn't care what precise
|
||||
meaning the timestamp has to the contract.
|
||||
|
||||
By creating a range that can be either closed or open at one end, we allow all of the following facts to be modelled:
|
||||
|
||||
* This transaction occurred at some point after the given time (e.g. after a maturity event)
|
||||
* This transaction occurred at any time before the given time (e.g. before a bankruptcy event)
|
||||
* This transaction occurred at some point roughly around the given time (e.g. on a specific day)
|
||||
|
||||
.. note:: It is assumed that the time feed for a notary is GPS/NaviStar time as defined by the atomic
|
||||
clocks at the US Naval Observatory. This time feed is extremely accurate and available globally for free.
|
||||
|
||||
Also see section 7 of the `Technical white paper`_ which covers this topic in significantly more depth.
|
||||
|
||||
.. _`Technical white paper`: _static/corda-technical-whitepaper.pdf
|
||||
|
62
docs/source/key-concepts-consensus.rst
Normal file
@ -0,0 +1,62 @@
|
||||
Consensus
|
||||
=========
|
||||
|
||||
.. topic:: Summary
|
||||
|
||||
* *To be committed, transactions must achieve both validity and uniqueness consensus*
|
||||
* *Validity consensus requires contractual validity of the transaction and all its dependencies*
|
||||
* *Uniqueness consensus prevents double-spends*
|
||||
|
||||
Two types of consensus
|
||||
----------------------
|
||||
Determining whether a proposed transaction is a valid ledger update involves reaching two types of consensus:
|
||||
|
||||
* *Validity consensus* - this is checked by each required signer before they sign the transaction
|
||||
* *Uniqueness consensus* - this is only checked by a notary service
|
||||
|
||||
Validity consensus
|
||||
------------------
|
||||
Validity consensus is the process of checking that the following conditions hold both for the proposed transaction,
|
||||
and for every transaction in the transaction chain that generated the inputs to the proposed transaction:
|
||||
|
||||
* The transaction is accepted by the contracts of every input and output state
|
||||
* The transaction has all the required signatures
|
||||
|
||||
It is not enough to verify the proposed transaction itself. We must also verify every transaction in the chain of
|
||||
transactions that led up to the creation of the inputs to the proposed transaction.
|
||||
|
||||
This is known as *walking the chain*. Suppose, for example, that a party on the network proposes a transaction
|
||||
transferring us a treasury bond. We can only be sure that the bond transfer is valid if:
|
||||
|
||||
* The treasury bond was issued by the central bank in a valid issuance transaction
|
||||
* Every subsequent transaction in which the bond changed hands was also valid
|
||||
|
||||
The only way to be sure of both conditions is to walk the transaction's chain. We can visualize this process as follows:
|
||||
|
||||
.. image:: resources/validation-consensus.png
|
||||
|
||||
When verifying a proposed transaction, a given party may not have every transaction in the transaction chain that they
|
||||
need to verify. In this case, they can request the missing transactions from the transaction proposer(s). The
|
||||
transaction proposer(s) will always have the full transaction chain, since they would have requested it when
|
||||
verifying the transaction that created the proposed transaction's input states.
|
||||
|
||||
Uniqueness consensus
|
||||
--------------------
|
||||
Imagine that Bob holds a valid central-bank-issued cash state of $1,000,000. Bob can now create two transaction
|
||||
proposals:
|
||||
|
||||
* A transaction transferring the $1,000,000 to Charlie in exchange for £800,000
|
||||
* A transaction transferring the $1,000,000 to Dan in exchange for €900,000
|
||||
|
||||
This is a problem because, although both transactions will achieve validity consensus, Bob has managed to
|
||||
"double-spend" his USD to get double the amount of GBP and EUR. We can visualize this as follows:
|
||||
|
||||
.. image:: resources/uniqueness-consensus.png
|
||||
|
||||
To prevent this, a valid transaction proposal must also achieve uniqueness consensus. Uniqueness consensus is the
|
||||
requirement that none of the inputs to a proposed transaction have already been consumed in another transaction.
|
||||
|
||||
If one or more of the inputs have already been consumed in another transaction, this is known as a *double spend*,
|
||||
and the transaction proposal is considered invalid.
|
||||
|
||||
Uniqueness consensus is provided by notaries. See :doc:`key-concepts-notaries` for more details.
|
73
docs/source/key-concepts-contracts.rst
Normal file
@ -0,0 +1,73 @@
|
||||
Contracts
|
||||
=========
|
||||
|
||||
.. topic:: Summary
|
||||
|
||||
* *A valid transaction must be accepted by the contract of each of its input and output states*
|
||||
* *Contracts are written in a JVM programming language (e.g. Java or Kotlin)*
|
||||
* *Contract execution is deterministic and its acceptance of a transaction is based on the transaction's contents alone*
|
||||
|
||||
Transaction verification
|
||||
------------------------
|
||||
Recall that a transaction is only valid if it is digitally signed by all required signers. However, even if a
|
||||
transaction gathers all the required signatures, it is only valid if it is also **contractually valid**.
|
||||
|
||||
**Contract validity** is defined as follows:
|
||||
|
||||
* Each state points to a *contract*
|
||||
* A *contract* takes a transaction as input, and states whether the transaction is considered valid based on the
|
||||
contract's rules
|
||||
* A transaction is only valid if the contract of **every input state** and **every output state** considers it to be
|
||||
valid
|
||||
|
||||
We can picture this situation as follows:
|
||||
|
||||
.. image:: resources/tx-validation.png
|
||||
|
||||
The contract code can be written in any JVM language, and has access to the full capabilities of the language,
|
||||
including:
|
||||
|
||||
* Checking the number of inputs, outputs, commands, timestamps, and/or attachments
|
||||
* Checking the contents of any of these components
|
||||
* Looping constructs, variable assignment, function calls, helper methods, etc.
|
||||
* Grouping similar states to validate them as a group (e.g. imposing a rule on the combined value of all the cash
|
||||
states)
|
||||
|
||||
A transaction that is not contractually valid is not a valid proposal to update the ledger, and thus can never be
|
||||
committed to the ledger. In this way, contracts impose rules on the evolution of states over time that are
|
||||
independent of the willingness of the required signers to sign a given transaction.
|
||||
|
||||
The contract sandbox
|
||||
--------------------
|
||||
Transaction verification must be *deterministic* - a contract should either **always accept** or **always reject** a
|
||||
given transaction. For example, transaction validity cannot depend on the time at which validation is conducted, or
|
||||
the amount of information the peer running the contract holds. This is a necessary condition to ensure that all peers
|
||||
on the network reach consensus regarding the validity of a given ledger update.
|
||||
|
||||
To achieve this, contracts evaluate transactions in a deterministic sandbox. The sandbox has a whitelist that
|
||||
prevents the contract from importing libraries that could be a source of non-determinism. This includes libraries
|
||||
that provide the current time, random number generators, libraries that provide filesystem access or networking
|
||||
libraries, for example. Ultimately, the only information available to the contract when verifying the transaction is
|
||||
the information included in the transaction itself.
|
||||
|
||||
Contract limitations
|
||||
--------------------
|
||||
Since a contract has no access to information from the outside world, it can only check the transaction for internal
|
||||
validity. It cannot check, for example, that the transaction is in accordance with what was originally agreed with the
|
||||
counterparties.
|
||||
|
||||
Peers should therefore check the contents of a transaction before signing it, *even if the transaction is
|
||||
contractually valid*, to see whether they agree with the proposed ledger update. A peer is under no obligation to
|
||||
sign a transaction just because it is contractually valid. For example, they may be unwilling to take on a loan that
|
||||
is too large, or may disagree on the amount of cash offered for an asset.
|
||||
|
||||
Oracles
|
||||
-------
|
||||
Sometimes, transaction validity will depend on some external piece of information, such as an exchange rate. In
|
||||
these cases, an oracle is required. See :doc:`key-concepts-oracles` for further details.
|
||||
|
||||
Legal prose
|
||||
-----------
|
||||
Each contract also refers to a legal prose document that states the rules governing the evolution of the state over
|
||||
time in a way that is compatible with traditional legal systems. This document can be relied upon in the case of
|
||||
legal disputes.
|
@ -1,142 +0,0 @@
|
||||
Data model
|
||||
==========
|
||||
|
||||
Overview
|
||||
--------
|
||||
Corda uses the so-called "UTXO set" model (unspent transaction output). In this model, the database
|
||||
does not track accounts or balances. An entry is either spent or not spent but it cannot be changed. In this model the
|
||||
database is a set of immutable rows keyed by (hash:output index). Transactions define outputs that append new rows and
|
||||
inputs which consume existing rows.
|
||||
|
||||
The Corda ledger is defined as a set of immutable **states**, which are created and destroyed by digitally signed **transactions**.
|
||||
Each transaction points to a set of states that it will consume/destroy, these are called **inputs**, and contains a set
|
||||
of new states that it will create, these are called **outputs**.
|
||||
Although the ledger is shared, it is not always the case that transactions and ledger entries are globally visible.
|
||||
In cases where a set of transactions stays within a small subgroup of users it is possible to keep the relevant
|
||||
data purely within that group. To ensure consistency, we rely heavily on secure hashes like SHA-256 to identify things.
|
||||
|
||||
The Corda model provides the following additional features:
|
||||
|
||||
* There is no global broadcast at any point.
|
||||
* States can include arbitrary typed data.
|
||||
* Transactions invoke not only input contracts but also the contracts of the outputs.
|
||||
* Contracts refer to a bundle of business logic that may handle various different tasks, beyond transaction verification.
|
||||
* Contracts are Turing-complete and can be written in any ordinary programming language that targets the JVM.
|
||||
* Arbitrarily-precise time-bounds may be specified in transactions (which must be attested to by a notary)
|
||||
* Primary consensus implementations use block-free conflict resolution algorithms.
|
||||
* Transactions are not ordered using a block chain and by implication Corda does not use miners or proof-of-work.
|
||||
Instead each state points to a notary, which is a service that guarantees it will sign a transaction only if all the
|
||||
input states are un-consumed.
|
||||
|
||||
Corda provides three main tools to achieve global distributed consensus:
|
||||
|
||||
* Smart contract logic to ensure state transitions are valid according to the pre-agreed rules.
|
||||
* Uniqueness and timestamping services to order transactions temporally and eliminate conflicts.
|
||||
* An :doc:`orchestration framework <key-concepts-flow-framework>` which simplifies the process of writing complex multi-step protocols between multiple different parties.
|
||||
|
||||
Comparisons of the Corda data model with Bitcoin and Ethereum can be found in the white papers.
|
||||
|
||||
States
|
||||
------
|
||||
A state object represents an agreement between two or more parties, the evolution of which governed by machine-readable contract code.
|
||||
This code references, and is intended to implement, portions of human-readable legal prose.
|
||||
It is intended to be shared only with those who have a legitimate reason to see it.
|
||||
|
||||
The following diagram illustrates a state object:
|
||||
|
||||
.. image:: resources/contract.png
|
||||
|
||||
In the diagram above, we see a state object representing a cash claim of £100 against a commercial bank, owned by a fictional shipping company.
|
||||
|
||||
.. note:: Legal prose (depicted above in grey-shade) is currently implemented as an unparsed reference to the natural language
|
||||
contract that the code is supposed to express (usually a hash of the contract's contents).
|
||||
|
||||
States contain arbitrary data, but they always contain at minimum a hash of the bytecode of a
|
||||
**contract code** file, which is a program expressed in JVM byte code that runs sandboxed inside a Java virtual machine.
|
||||
Contract code (or just "contracts" in the rest of this document) are globally shared pieces of business logic.
|
||||
|
||||
.. note:: In the current code dynamic loading of contracts is not implemented. This will change in the near future.
|
||||
|
||||
Contracts
|
||||
---------
|
||||
Contracts define part of the business logic of the ledger.
|
||||
|
||||
Corda enforces business logic through smart contract code, which is constructed as a pure function (called "verify") that either accepts
|
||||
or rejects a transaction, and which can be composed from simpler, reusable functions. The functions interpret transactions
|
||||
as taking states as inputs and producing output states through the application of (smart contract) commands, and accept
|
||||
the transaction if the proposed actions are valid. Given the same transaction, a contract’s “verify” function always yields
|
||||
exactly the same result. Contracts do not have storage or the ability to interact with anything.
|
||||
|
||||
.. note:: In the future, contracts will be mobile. Nodes will download and run contracts inside a sandbox without any review in some deployments,
|
||||
although we envisage the use of signed code for Corda deployments in the regulated sphere. Corda will use an augmented
|
||||
JVM custom sandbox that is radically more restrictive than the ordinary JVM sandbox, and it will enforce not only
|
||||
security requirements but also deterministic execution.
|
||||
|
||||
To further aid writing contracts we introduce the concept of :doc:`clauses` which provide a means of re-using common
|
||||
verification logic.
|
||||
|
||||
Transactions
|
||||
------------
|
||||
Transactions are used to update the ledger by consuming existing state objects and producing new state objects.
|
||||
|
||||
A transaction update is accepted according to the following two aspects of consensus:
|
||||
|
||||
#. Transaction validity: parties can ensure that the proposed transaction and all its ancestors are valid
|
||||
by checking that the associated contract code runs successfully and has all the required signatures
|
||||
#. Transaction uniqueness: parties can ensure there exists no other transaction, over which we have previously reached
|
||||
consensus (validity and uniqueness), that consumes any of the same states. This is the responsibility of a notary service.
|
||||
|
||||
Beyond inputs and outputs, transactions may also contain **commands**, small data packets that
|
||||
the platform does not interpret itself but which parameterise execution of the contracts. They can be thought of as
|
||||
arguments to the verify function. Each command has a list of **composite keys** associated with it. The platform ensures
|
||||
that the transaction has signatures matching every key listed in the commands before the contracts start to execute. Thus, a verify
|
||||
function can trust that all listed keys have signed the transaction, but is responsible for verifying that any keys required
|
||||
for the transaction to be valid from the verify function's perspective are included in the list. Public keys
|
||||
may be random/identityless for privacy, or linked to a well known legal identity, for example via a
|
||||
*public key infrastructure* (PKI).
|
||||
|
||||
.. note:: Linkage of keys with identities via a PKI is only partially implemented in the current code.
|
||||
|
||||
Commands are always embedded inside a transaction. Sometimes, there's a larger piece of data that can be reused across
|
||||
many different transactions. For this use case, we have **attachments**. Every transaction can refer to zero or more
|
||||
attachments by hash. Attachments are always ZIP/JAR files, which may contain arbitrary content. These files are
|
||||
then exposed on the classpath and so can be opened by contract code in the same manner as any JAR resources
|
||||
would be loaded.
|
||||
|
||||
Note that there is nothing that explicitly binds together specific inputs, outputs, commands or attachments. Instead,
|
||||
it's up to the contract code to interpret the pieces inside the transaction and ensure they fit together correctly. This
|
||||
is done to maximise flexibility for the contract developer.
|
||||
|
||||
Transactions may sometimes need to provide a contract with data from the outside world. Examples may include stock
|
||||
prices, facts about events or the statuses of legal entities (e.g. bankruptcy), and so on. The providers of such
|
||||
facts are called **oracles** and they provide facts to the ledger by signing transactions that contain commands they
|
||||
recognise, or by creating signed attachments. The commands contain the fact and the signature shows agreement to that fact.
|
||||
|
||||
Time is also modelled as a fact and represented as a **timestamping command** placed inside the transaction. This specifies a
|
||||
time window in which the transaction is considered valid for notarisation. The time window can be open ended (i.e. with a start but no end or vice versa).
|
||||
In this way transactions can be linked to the notary's clock.
|
||||
|
||||
It is possible for a single Corda network to have multiple competing notaries. A new (output) state is tied to a specific
|
||||
notary when it is created. Transactions can only consume (input) states that are all associated with the same notary.
|
||||
A special type of transaction is provided that can move a state (or set of states) from one notary to another.
|
||||
|
||||
.. note:: Currently the platform code will not automatically re-assign states to a single notary. This is a future planned feature.
|
||||
|
||||
Transaction Validation
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
When a transaction is presented to a node as part of a flow it may need to be checked. Checking original transaction validity is
|
||||
the responsibility of the ``ResolveTransactions`` flow. This flow performs a breadth-first search over the transaction graph,
|
||||
downloading any missing transactions into local storage and validating them. The search bottoms out at transactions without inputs
|
||||
(eg. these are mostly created from issuance transactions). A transaction is not considered valid if any of its transitive dependencies are invalid.
|
||||
|
||||
.. note:: Non-validating notaries assume transaction validity and do not request transaction data or their dependencies
|
||||
beyond the list of states consumed.
|
||||
|
||||
The tutorial ":doc:`tutorial-contract`" provides a hand-ons walk-through using these concepts.
|
||||
|
||||
Transaction Representation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
By default, all transaction data (input and output states, commands, attachments) is visible to all participants in
|
||||
a multi-party, multi-flow business workflow. :doc:`merkle-trees` describes how Corda uses Merkle trees to
|
||||
ensure data integrity and hiding of sensitive data within a transaction that shouldn't be visible in its entirety to all
|
||||
participants (eg. oracles nodes providing facts).
|
@ -1,47 +1,51 @@
|
||||
Corda ecosystem
|
||||
===============
|
||||
The network
|
||||
===========
|
||||
|
||||
A Corda network consists of the following components:
|
||||
.. topic:: Summary
|
||||
|
||||
* Nodes, where each node represents a JVM run-time environment hosting Corda services and executing applications ("CorDapps").
|
||||
Nodes communicate using AMQP/1.0 over TLS.
|
||||
* A permissioning service that automates the process of provisioning TLS certificates.
|
||||
* A network map service that publishes information about nodes on the network.
|
||||
* One or more pluggable notary service types (which may be distributed over multiple nodes).
|
||||
A notary guarantees uniqueness and validity of transactions.
|
||||
* Zero or more oracle services. An oracle is a well known service that signs transactions if they state a fact and that fact is considered to be true.
|
||||
* CorDapps which represent participant applications that execute contract code and communicate using the flow framework to achieve consensus over some business activity
|
||||
* Standalone Corda applications that provide manageability and tooling support to a Corda network.
|
||||
* *A Corda network is made up of nodes running Corda and CorDapps*
|
||||
* *The network is permissioned, with access controlled by a doorman*
|
||||
* *Communication between nodes is point-to-point, instead of relying on global broadcasts*
|
||||
|
||||
Network structure
|
||||
-----------------
|
||||
A Corda network is an authenticated peer-to-peer network of nodes, where each node is a JVM run-time environment
|
||||
hosting Corda services and executing applications known as *CorDapps*.
|
||||
|
||||
All communication between nodes is direct, with TLS-encrypted messages sent over AMQP/1.0. This means that data is
|
||||
shared only on a need-to-know basis; in Corda, there are **no global broadcasts**.
|
||||
|
||||
Each network has a **network map service** that publishes the IP addresses through which every node on the network can
|
||||
be reached, along with the identity certificates of those nodes and the services they provide.
|
||||
|
||||
The doorman
|
||||
-----------
|
||||
Corda networks are semi-private. Each network has a doorman service that enforces rules regarding the information
|
||||
that nodes must provide and the know-your-customer processes that they must complete before being admitted to the
|
||||
network.
|
||||
|
||||
To join the network, a node must contact the doorman and provide the required information. If the doorman is
|
||||
satisfied, the node will receive a root-authority-signed TLS certificate from the network's permissioning service.
|
||||
This certificate certifies the node's identity when communicating with other participants on the network.
|
||||
|
||||
We can visualize a network as follows:
|
||||
|
||||
.. image:: resources/network.png
|
||||
|
||||
Network services
|
||||
----------------
|
||||
Nodes can provide several types of services:
|
||||
|
||||
* One or more pluggable **notary services**. Notaries guarantee the uniqueness, and possibility the validity, of ledger
|
||||
updates. Each notary service may be run on a single node, or across a cluster of nodes.
|
||||
* Zero or more **oracle services**. An oracle is a well-known service that signs transactions if they state a fact and
|
||||
that fact is considered to be true.
|
||||
|
||||
These components are illustrated in the following diagram:
|
||||
|
||||
.. image:: resources/cordaNetwork.png
|
||||
:align: center
|
||||
|
||||
Note:
|
||||
|
||||
* Corda infrastructure services are those which all participants depend upon, such as the network map and notaries.
|
||||
* Corda services can be deployed by participants, third parties or a central network operator (eg. such as R3);
|
||||
this diagram is not intended to imply only a centralised model is supported
|
||||
|
||||
It is important to highlight the following:
|
||||
|
||||
* Corda is designed for semi-private networks in which admission requires obtaining an identity signed by a root authority.
|
||||
* Nodes are arranged in an authenticated peer to peer network. All communication is direct.
|
||||
* Data is shared on a need-to-know basis. Nodes provide the dependency graph of a transaction they are sending to another node on demand, but there is no global broadcast of all transactions.
|
||||
* Nodes are backed by a relational database and data placed in the ledger can be queried using SQL
|
||||
* The network map publishes the IP addresses through which every node on the network can be reached, along with the identity certificates of those nodes and the services they provide.
|
||||
* All communication takes the form of small multi-party sub-protocols called flows.
|
||||
* Oracles represent gateways to proprietary (or other) business logic executors (e.g., central counterparties or valuation agents) that can be verified on-ledger by participants.
|
||||
|
||||
CorDapps
|
||||
--------
|
||||
Corda is a platform for the writing of “CorDapps”: applications that extend the distributed ledger with new capabilities.
|
||||
Such apps define new data types, new inter-node protocol flows and the “smart contracts” that determine allowed changes.
|
||||
The combination of state objects (data), contract code (allowable operations), transaction flows (business logic
|
||||
choreography), any necessary APIs, vault plugins, and UI components can be thought of as a shared ledger application,
|
||||
or corda distributed application (“CorDapp”). This is the core set of components a contract developer on the platform
|
||||
should expect to build.
|
||||
|
||||
Examples of CorDapps include asset trading (see :ref:`irs-demo` and :ref:`trader-demo`), portfolio valuations (see :ref:`simm-demo`), trade finance,
|
||||
post-trade order matching, KYC/AML, etc.
|
||||
In this diagram, Corda infrastructure services are those upon which all participants depend, such as the network map
|
||||
and notary services. Corda services may be deployed by participants, third parties or a central network operator
|
||||
(such as R3). The diagram is not intended to imply that only a centralised model is supported.
|
@ -1,37 +0,0 @@
|
||||
|
||||
Flow framework
|
||||
--------------
|
||||
In Corda all communication takes the form of structured sequences of messages passed between parties which we call flows.
|
||||
|
||||
Flows enable complex multi-step, multi-party business interactions to be modelled as blocking code without a central controller.
|
||||
The code is transformed into an asynchronous state machine, with checkpoints written to the node’s backing database when messages are sent and received.
|
||||
A node may potentially have millions of flows active at once and they may last days, across node restarts and even upgrades.
|
||||
|
||||
A flow library is provided to enable developers to re-use common flow types such as notarisation, membership broadcast,
|
||||
transaction resolution and recording, and so on.
|
||||
|
||||
APIs are provided to send and receive object graphs to and from other identities on the network, embed sub-flows,
|
||||
report progress information to observers and even interact with people (for manual resolution of exceptional scenarios)
|
||||
|
||||
Flows are embedded within CorDapps and deployed to a participant's node for execution.
|
||||
|
||||
.. note:: We will be implementing the concept of a flow hospital to provide a means for a node administrator to decide
|
||||
whether a paused flow should be killed or repaired. Flows enter this state if they throw exceptions or explicitly request human assistance.
|
||||
|
||||
Section 4 of the `Technical white paper`_ provides further detail of the above features.
|
||||
|
||||
The following diagram illustrates a sample multi-party business flow:
|
||||
|
||||
.. image:: resources/flowFramework.png
|
||||
|
||||
Note the following:
|
||||
|
||||
* there are 3 participants in this workflow including the notary
|
||||
* the Buyer and Seller flows (depicted in green) are custom written by developers and deployed within a CorDapp
|
||||
* the custom written flows invoke both financial library flows such as ``TwoPartyTradeFlow`` (depicted in orange) and core
|
||||
library flows such as ``ResolveTransactionsFlow`` and ``NotaryFlow`` (depicted in yellow)
|
||||
* each side of the flow illustrates the stage of execution with a progress tracker notification
|
||||
* activities within a flow directly or indirectly interact with its node's ledger (eg. to record a signed, notarised transaction) and vault (eg. to perform a spend of some fungible asset)
|
||||
* flows interact across parties using send, receive and sendReceive messaging semantics (by implementing the ``FlowLogic`` interface)
|
||||
|
||||
.. _`Technical white paper`: _static/corda-technical-whitepaper.pdf
|
48
docs/source/key-concepts-flows.rst
Normal file
@ -0,0 +1,48 @@
|
||||
Flows
|
||||
=====
|
||||
|
||||
.. topic:: Summary
|
||||
|
||||
* *Flows automate the process of agreeing ledger updates*
|
||||
* *Communication between nodes only occurs in the context of these flows, and is point-to-point*
|
||||
* *Built-in flows are provided to automate common tasks*
|
||||
|
||||
Corda networks use point-to-point messaging instead of a global broadcast. This means that coordinating a ledger update
|
||||
requires network participants to specify exactly what information needs to be sent, to which counterparties, and in
|
||||
what order.
|
||||
|
||||
Rather than having to specify these steps manually, Corda automates the process using *flows*. A flow is a sequence
|
||||
of actions that tells a node how to achieve a specific ledger update, such as issuing an asset or settling a trade.
|
||||
|
||||
Once a given business process has been encapsulated in a flow and installed on the node as part of a CorDapp, the node's
|
||||
owner can instruct the node to kick off this business process at any time with a simple RPC call. All activity on the
|
||||
node, and all inter-node communication, occurs in the context of these flows.
|
||||
|
||||
A flow's steps may include:
|
||||
|
||||
* Identifying counterparties on the network
|
||||
* Extracting information from the vault or local storage
|
||||
* Building a transaction
|
||||
* Sending messages
|
||||
* Notarising and recording a transaction
|
||||
* Reporting progress to observers
|
||||
* Requesting human interaction...
|
||||
|
||||
A node can have millions of flows active at once and they may last days, across node restarts and even upgrades.
|
||||
|
||||
An example flow
|
||||
---------------
|
||||
Here is a visualisation of an example flow, showing Alice and Bob agreeing on a ledger update:
|
||||
|
||||
.. image:: resources/flow.gif
|
||||
|
||||
The flow library
|
||||
----------------
|
||||
Corda provides a library of flows to handle common tasks, meaning that developers do not have to redefine the
|
||||
logic behind common processes such as:
|
||||
|
||||
* Notarising and recording a transaction
|
||||
* Gathering signatures from counterparty nodes
|
||||
* Verifying a chain of transactions
|
||||
|
||||
Further information on the available built-in flows can be found in :doc:`flow-library`.
|
26
docs/source/key-concepts-ledger.rst
Normal file
@ -0,0 +1,26 @@
|
||||
The ledger
|
||||
==========
|
||||
|
||||
.. topic:: Summary
|
||||
|
||||
* *The ledger is subjective from each peer's perspective*
|
||||
* *Two peers are always guaranteed to see the exact same version of any on-ledger facts they share*
|
||||
|
||||
Overview
|
||||
--------
|
||||
In Corda, there is **no single central store of data**. Instead, each node maintains a separate database of known
|
||||
facts. As a result, each peer only sees a subset of facts on the ledger, and no peer is aware of the ledger in its
|
||||
entirety.
|
||||
|
||||
For example, imagine a network with five nodes, where each coloured circle represents a shared fact:
|
||||
|
||||
.. image:: resources/ledger-venn.png
|
||||
|
||||
We can see that although Carl, Demi and Ed are aware of shared fact 3, **Alice and Bob are not**.
|
||||
|
||||
Equally importantly, Corda guarantees that whenever one of these facts is shared by multiple nodes on the network, it evolves
|
||||
in lockstep in the database of every node that is aware of it:
|
||||
|
||||
.. image:: resources/ledger-table.png
|
||||
|
||||
For example, Alice and Bob will both see the **exact same version** of shared facts 1 and 7.
|
72
docs/source/key-concepts-node.rst
Normal file
@ -0,0 +1,72 @@
|
||||
Nodes
|
||||
=====
|
||||
|
||||
.. topic:: Summary
|
||||
|
||||
* *A node is JVM run-time with a unique network identity running the Corda software*
|
||||
* *The node has two interfaces with the outside world:*
|
||||
|
||||
* *A network layer, for interacting with other nodes*
|
||||
* *RPC, for interacting with the node's owner*
|
||||
|
||||
* *The node's functionality is extended by installing CorDapps in the plugin registry*
|
||||
|
||||
Node architecture
|
||||
-----------------
|
||||
A Corda node is a JVM run-time environment with a unique identity on the network that hosts Corda services and
|
||||
CorDapps.
|
||||
|
||||
We can visualize the node's internal architecture as follows:
|
||||
|
||||
.. image:: resources/node-architecture.png
|
||||
|
||||
The core elements of the architecture are:
|
||||
|
||||
* A persistence layer for storing data
|
||||
* A network interface for interacting with other nodes
|
||||
* An RPC interface for interacting with the node's owner
|
||||
* A service hub for allowing the node's flows to call upon the node's other services
|
||||
* A plugin registry for extending the node by installing CorDapps
|
||||
|
||||
Persistence layer
|
||||
-----------------
|
||||
The persistence layer has two parts:
|
||||
|
||||
* The **vault**, where the node stores any relevant current and historic states
|
||||
* The **storage service**, where it stores transactions, attachments and flow checkpoints
|
||||
|
||||
The node's owner can query the node's storage using the RPC interface (see below).
|
||||
|
||||
Network interface
|
||||
-----------------
|
||||
All communication with other nodes on the network is handled by the node itself, as part of running a flow. The
|
||||
node's owner does not interact with other network nodes directly.
|
||||
|
||||
RPC interface
|
||||
-------------
|
||||
The node's owner interacts with the node via remote procedure calls (RPC). RPC operations exposed by the node include:
|
||||
|
||||
* Starting a flow
|
||||
* Reading the contents of the vault or the transaction storage
|
||||
* Uploading and downloading attachments
|
||||
|
||||
The service hub
|
||||
---------------
|
||||
Internally, the node has access to a rich set of services that are used during flow execution to coordinate ledger
|
||||
updates. The key services provided are:
|
||||
|
||||
* Information on other nodes on the network and the services they offer
|
||||
* Access to the contents of the vault and the storage service
|
||||
* Access to, and generation of, the node's public-private keypairs
|
||||
* Information about the node itself
|
||||
* The current time, as tracked by the node
|
||||
|
||||
The plugin registry
|
||||
-------------------
|
||||
The plugin registry is where new CorDapps are installed to extend the behavior of the node.
|
||||
|
||||
The node also has several plugins installed by default to handle common tasks such as:
|
||||
|
||||
* Retrieving transactions and attachments from counterparties
|
||||
* Upgrading contracts
|
||||
* Broadcasting agreed ledger updates for recording by counterparties
|
88
docs/source/key-concepts-notaries.rst
Normal file
@ -0,0 +1,88 @@
|
||||
Notaries
|
||||
========
|
||||
|
||||
.. topic:: Summary
|
||||
|
||||
* *Notaries prevent "double-spends"*
|
||||
* *Notaries may optionally also validate transactions*
|
||||
* *A network can have several notaries, each running a different consensus algorithm*
|
||||
|
||||
Notarisation
|
||||
------------
|
||||
A *notary* is a network service that provides **uniqueness consensus** by attesting that, for a given transaction, it
|
||||
has not already signed other transactions that consumes any of the proposed transaction's input states.
|
||||
|
||||
Upon being sent asked to notarise a transaction, a notary will either:
|
||||
|
||||
* Sign the transaction if it has not already signed other transactions consuming any of the proposed transaction's
|
||||
input states
|
||||
* Reject the transaction and flag that a double-spend attempt has occurred otherwise
|
||||
|
||||
In doing so, the notary provides the point of finality in the system. Until the notary's signature is obtained, parties
|
||||
cannot be sure that an equally valid, but conflicting, transaction will not be regarded as the "valid" attempt to spend
|
||||
a given input state. However, after the notary's signature is obtained, we can be sure that the proposed
|
||||
transaction's input states had not already been consumed by a prior transaction. Hence, notarisation is the point
|
||||
of finality in the system.
|
||||
|
||||
Every state has an appointed notary, and a notary will only notarise a transaction if it is the appointed notary
|
||||
of all the transaction's input states.
|
||||
|
||||
Consensus algorithms
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
Corda has "pluggable" consensus, allowing notaries to choose a consensus algorithm based on their requirements in
|
||||
terms of privacy, scalability, legal-system compatibility and algorithmic agility.
|
||||
|
||||
In particular, notaries may differ in terms of:
|
||||
|
||||
* **Structure** - a notary may be a single network node, a cluster of mutually-trusting nodes, or a cluster of
|
||||
mutually-distrusting nodes
|
||||
* **Consensus algorithm** - a notary service may choose to run a high-speed, high-trust algorithm such as RAFT, a
|
||||
low-speed, low-trust algorithm such as BFT, or any other consensus algorithm it chooses
|
||||
|
||||
Validation
|
||||
^^^^^^^^^^
|
||||
A notary service must also decide whether or not to provide **validity consensus** by validating each transaction
|
||||
before committing it. In making this decision, they face the following trade-off:
|
||||
|
||||
* If a transaction **is not** checked for validity, it creates the risk of "denial of state" attacks, where a node
|
||||
knowingly builds an invalid transaction consuming some set of existing states and sends it to the
|
||||
notary, causing the states to be marked as consumed
|
||||
|
||||
* If the transaction **is** checked for validity, the notary will need to see the full contents of the transaction and
|
||||
its dependencies. This leaks potentially private data to the notary
|
||||
|
||||
There are several further points to keep in mind when evaluating this trade-off. In the case of the non-validating
|
||||
model, Corda's controlled data distribution model means that information on unconsumed states is not widely shared.
|
||||
Additionally, Corda's permissioned network means that the notary can store to the identity of the party that created
|
||||
the "denial of state" transaction, allowing the attack to be resolved off-ledger.
|
||||
|
||||
In the case of the validating model, the use of anonymous, freshly-generated public keys instead of legal identities to
|
||||
identify parties in a transaction limit the information the notary sees.
|
||||
|
||||
Multiple notaries
|
||||
^^^^^^^^^^^^^^^^^
|
||||
Each Corda network can have multiple notaries, each potentially running a different consensus algorithm. This provides
|
||||
several benefits:
|
||||
|
||||
* **Privacy** - we can have both validating and non-validating notary services on the same network, each running a
|
||||
different algorithm. This allows nodes to choose the preferred notary on a per-transaction basis
|
||||
* **Load balancing** - spreading the transaction load over multiple notaries allows higher transaction throughput for
|
||||
the platform overall
|
||||
* **Low latency** - latency can be minimised by choosing a notary physically closer to the transacting parties
|
||||
|
||||
Changing notaries
|
||||
^^^^^^^^^^^^^^^^^
|
||||
Remember that a notary will only sign a transaction if it is the appointed notary of all of the transaction's input
|
||||
states. However, there are cases in which we may need to change a state's appointed notary. These include:
|
||||
|
||||
* When a single transaction needs to consume several states that have different appointed notaries
|
||||
* When a node would prefer to use a different notary for a given transaction due to privacy or efficiency concerns
|
||||
|
||||
Before these transactions can be created, the states must first be repointed to all have the same notary. This is
|
||||
achieved using a special notary-change transaction that takes:
|
||||
|
||||
* A single input state
|
||||
* An output state identical to the input state, except that the appointed notary has been changed
|
||||
|
||||
The input state's appointed notary will sign the transaction if it doesn't constitute a double-spend, at which point
|
||||
a state will enter existence that has all the properties of the old state, but has a different appointed notary.
|
26
docs/source/key-concepts-oracles.rst
Normal file
@ -0,0 +1,26 @@
|
||||
Oracles
|
||||
=======
|
||||
|
||||
.. topic:: Summary
|
||||
|
||||
* *A fact can be included in a transaction as part of a command*
|
||||
* *An oracle is a service that will only sign the transaction if the included fact is true*
|
||||
|
||||
In many cases, a transaction's contractual validity depends on some external piece of data, such as the current
|
||||
exchange rate. However, if we were to let each participant evaluate the transaction's validity based on their own
|
||||
view of the current exchange rate, the contract's execution would be non-deterministic: some signers would consider the
|
||||
transaction valid, while others would consider it invalid. As a result, disagreements would arise over the true state
|
||||
of the ledger.
|
||||
|
||||
Corda addresses this issue using *oracles*. Oracles are network services that, upon request, provide commands
|
||||
that encapsulate a specific fact (e.g. the exchange rate at time x) and list the oracle as a required signer.
|
||||
|
||||
If a node wishes to use a given fact in a transaction, they request a command asserting this fact from the oracle. If
|
||||
the oracle considers the fact to be true, they send back the required command. The node then includes the command in
|
||||
their transaction, and the oracle will sign the transaction to assert that the fact is true.
|
||||
|
||||
If they wish to monetize their services, oracles can choose to only sign a transaction and attest to the validity of
|
||||
the fact it contains for a fee.
|
||||
|
||||
Transaction tear-offs are used to prevent the oracle from seeing information about the transaction that is not
|
||||
relevant to them. See :doc:`merkle-trees` for further details.
|
@ -1,45 +0,0 @@
|
||||
Security model
|
||||
==============
|
||||
|
||||
Corda has been designed from the ground up to implement a global, decentralised database where all nodes are assumed to be
|
||||
untrustworthy. This means that each node must actively cross-check each other's work to reach consensus
|
||||
amongst a group of interacting participants.
|
||||
|
||||
The security model plays a role in the following areas:
|
||||
|
||||
* Identity:
|
||||
Corda is designed for semi-private networks in which admission requires obtaining an identity signed by a root authority.
|
||||
This assumption is pervasive – the flow API provides messaging in terms of identities, with routing and delivery to underlying nodes being handled automatically.
|
||||
See sections 3.2 of the `Technical white paper`_ for further details on identity and the permissioning service.
|
||||
|
||||
* Notarisation: pluggable notaries and algorithms offering different levels of trust.
|
||||
Notaries may be validating or non-validating. A validating notary will resolve and fully check transactions they are asked to deconflict.
|
||||
Without the use of any other privacy features, they gain full visibility into every transaction.
|
||||
On the other hand, non-validating notaries assume transaction validity and do not request transaction data or their dependencies
|
||||
beyond the list of states consumed (and thus, their level of trust is much lower and exposed to malicious use of transaction inputs).
|
||||
From an algorithm perspective, Corda currently provides a distributed notary implementation that uses Raft.
|
||||
|
||||
.. note:: A byzantine fault tolerant notary based on the BFT-SMaRT algorithm is included in the code, but is
|
||||
still incubating and is not yet ready for use.
|
||||
|
||||
* Authentication, authorisation and entitlements:
|
||||
Network permissioning, including node to node authentication, is performed using TLS and certificates.
|
||||
See :doc:`permissioning` for further detail.
|
||||
|
||||
.. warning:: API level authentication (RPC, Web) is currently simple username/password for demonstration purposes and will be revised.
|
||||
Similarly, authorisation is currently based on permission groups applied to flow execution.
|
||||
|
||||
Privacy techniques
|
||||
|
||||
* Partial data visibility: transactions are not globally broadcast as in many other systems.
|
||||
* Transaction tear-offs: Transactions are structured as Merkle trees, and may have individual subcomponents be revealed to parties who already know the Merkle root hash. Additionally, they may sign the transaction without being able to see all of it.
|
||||
|
||||
See :doc:`merkle-trees` for further detail.
|
||||
|
||||
* Multi-signature support: Corda uses composite keys to support scenarios where more than one key or party is required to authorise a state object transition.
|
||||
|
||||
.. note:: Future privacy techniques will include key randomisation, graph pruning, deterministic JVM sandboxing and support for secure signing devices.
|
||||
See sections 10 and 13 of the `Technical white paper`_ for detailed descriptions of these techniques and features.
|
||||
|
||||
.. _`Technical white paper`: _static/corda-technical-whitepaper.pdf
|
||||
|
44
docs/source/key-concepts-states.rst
Normal file
@ -0,0 +1,44 @@
|
||||
States
|
||||
======
|
||||
|
||||
.. topic:: Summary
|
||||
|
||||
* *States represent on-ledger facts*
|
||||
* *States are evolved by marking the current state as historic and creating an updated state*
|
||||
* *Each node has a vault where it stores any relevant states to itself*
|
||||
|
||||
A *state* is an immutable object representing a fact known by one or more Corda nodes at a specific point in time.
|
||||
States can contain arbitrary data, allowing them to represent facts of any kind (e.g. stocks, bonds, loans, KYC data,
|
||||
identity information...).
|
||||
|
||||
For example, the following state represents an IOU - an agreement that Alice owes Bob an amount X:
|
||||
|
||||
.. image:: resources/state.png
|
||||
|
||||
Specifically, this state represents an IOU of £10 from Alice to Bob.
|
||||
|
||||
As well as any information about the fact itself, the state also contains a reference to the *contract* that governs
|
||||
the evolution of the state over time. We discuss contracts in :doc:`key-concepts-contracts`.
|
||||
|
||||
State sequences
|
||||
---------------
|
||||
As states are immutable, they cannot be modified directly to reflect a change in the state of the world.
|
||||
|
||||
Instead, the lifecycle of a shared fact over time is represented by a **state sequence**. When a state needs to be
|
||||
updated, we create a new version of the state representing the new state of the world, and mark the existing state as
|
||||
historic.
|
||||
|
||||
This sequence of state replacements gives us a full view of the evolution of the shared fact over time. We can
|
||||
picture this situation as follows:
|
||||
|
||||
.. image:: resources/state-sequence.png
|
||||
|
||||
The vault
|
||||
---------
|
||||
Each node on the network maintains a *vault* - a database where it tracks all the current and historic states that it
|
||||
is aware of, and which it considers to be relevant to itself:
|
||||
|
||||
.. image:: resources/vault-simple.png
|
||||
|
||||
We can think of the ledger from each node's point of view as the set of all the current (i.e. non-historic) states that
|
||||
it is aware of.
|
50
docs/source/key-concepts-time-windows.rst
Normal file
@ -0,0 +1,50 @@
|
||||
Time-windows
|
||||
============
|
||||
|
||||
.. topic:: Summary
|
||||
|
||||
* *If a transaction includes a time-window, it can only be committed during that window*
|
||||
* *The notary is the timestamping authority, refusing to commit transactions outside of that window*
|
||||
* *Time-windows can have a start and end time, or be open at either end*
|
||||
|
||||
Time in a distributed system
|
||||
----------------------------
|
||||
A notary also act as the *timestamping authority*, verifying that a transaction occurred during a specific time-window
|
||||
before notarising it.
|
||||
|
||||
For a time-window to be meaningful, its implications must be binding on the party requesting it. A party can obtain a
|
||||
time-window signature in order to prove that some event happened *before*, *on*, or *after* a particular point in time.
|
||||
However, if the party is not also compelled to commit to the associated transaction, it has a choice of whether or not
|
||||
to reveal this fact until some point in the future. As a result, we need to ensure that the notary either has to also
|
||||
sign the transaction within some time tolerance, or perform timestamping *and* notarisation at the same time. The
|
||||
latter is the chosen behaviour for this model.
|
||||
|
||||
There will never be exact clock synchronisation between the party creating the transaction and the notary.
|
||||
This is not only due to issues of physics and network latency, but also because between inserting the command and
|
||||
getting the notary to sign there may be many other steps (e.g. sending the transaction to other parties involved in the
|
||||
trade, requesting human sign-off...). Thus the time at which the transaction is sent for notarisation may be quite
|
||||
different to the time at which the transaction was created.
|
||||
|
||||
Time-windows
|
||||
------------
|
||||
For this reason, times in transactions are specified as time *windows*, not absolute times. In a distributed system
|
||||
there can never be "true time", only an approximation of it. Time windows can be open-ended (i.e. specify only one of
|
||||
"before" and "after") or they can be fully bounded.
|
||||
|
||||
.. image:: resources/time-window.gif
|
||||
|
||||
In this way, we express the idea that the *true value* of the fact "the current time" is actually unknowable. Even when
|
||||
both a before and an after time are included, the transaction could have occurred at any point within that time-window.
|
||||
|
||||
By creating a range that can be either closed or open at one end, we allow all of the following situations to be
|
||||
modelled:
|
||||
|
||||
* A transaction occurring at some point after the given time (e.g. after a maturity event)
|
||||
* A transaction occurring at any time before the given time (e.g. before a bankruptcy event)
|
||||
* A transaction occurring at some point roughly around the given time (e.g. on a specific day)
|
||||
|
||||
If a time window needs to be converted to an absolute time (e.g. for display purposes), there is a utility method to
|
||||
calculate the mid point.
|
||||
|
||||
.. note:: It is assumed that the time feed for a notary is GPS/NaviStar time as defined by the atomic
|
||||
clocks at the US Naval Observatory. This time feed is extremely accurate and available globally for free.
|
76
docs/source/key-concepts-tradeoffs.rst
Normal file
@ -0,0 +1,76 @@
|
||||
Tradeoffs
|
||||
=========
|
||||
|
||||
.. topic:: Summary
|
||||
|
||||
* *Permissioned networks are better suited for financial use-cases*
|
||||
* *Point-to-point communication allows information to be shared need-to-know*
|
||||
* *A UTXO model allows for more transactions-per-second*
|
||||
|
||||
Permissioned vs. permissionless
|
||||
-------------------------------
|
||||
Traditional blockchain networks are *permissionless*. The parties on the network are anonymous, and can join and
|
||||
leave at will.
|
||||
|
||||
By contrast, Corda networks are *permissioned*. Each party on the network has a known identity that they use when
|
||||
communicating with counterparties, and network access is controlled by a doorman. This has several benefits:
|
||||
|
||||
* Anonymous parties are inappropriate for most scenarios involving regulated financial institutions
|
||||
* Knowing the identity of your counterparties allows for off-ledger resolution of conflicts using existing
|
||||
legal systems
|
||||
* Sybil attacks are averted without the use of expensive mechanisms such as proof-of-work
|
||||
|
||||
Point-to-point vs. global broadcasts
|
||||
------------------------------------
|
||||
Traditional blockchain networks broadcast every message to every participant. The reason for this is two-fold:
|
||||
|
||||
* Counterparty identities are not known, so a message must be sent to every participant to ensure it reaches its
|
||||
intended recipient
|
||||
* Making every participant aware of every transaction allows the network to prevent double-spends
|
||||
|
||||
The downside is that all participants see everyone else's data. This is unacceptable for many use-cases.
|
||||
|
||||
In Corda, each message is instead addressed to a specific counterparty, and is not seen by any uninvolved third
|
||||
parties. The developer has full control over what messages are sent, to whom, and in what order. As a result, **data
|
||||
is shared on a need-to-know basis only**. To prevent double-spends in this system, we employ notaries as
|
||||
an alternative to proof-of-work.
|
||||
|
||||
Corda also uses several other techniques to maximize privacy on the network:
|
||||
|
||||
* **Transaction tear-offs**: Transactions are structured in a way that allows them to be digitally signed without
|
||||
disclosing the transaction's contents. This is achieved using a data structure called a Merkle tree. You can read
|
||||
more about this technique in :doc:`merkle-trees`.
|
||||
* **Key randomisation**: The parties to a transaction are identified only by their public keys, and fresh keypairs are
|
||||
generated for each transaction. As a result, an onlooker cannot identify which parties were involved in a given
|
||||
transaction.
|
||||
|
||||
UTXO vs. account model
|
||||
----------------------
|
||||
Corda uses a *UTXO* (unspent transaction output) model. Each transaction consumes a set of existing states to produce
|
||||
a set of new states.
|
||||
|
||||
The alternative would be an *account* model. In an account model, stateful objects are stored on-ledger, and
|
||||
transactions take the form of requests to update the current state of these objects.
|
||||
|
||||
The main advantage of the UTXO model is that transactions with different inputs can be applied in parallel,
|
||||
vastly increasing the network's potential transactions-per-second. In the account model, the number of
|
||||
transactions-per-second is limited by the fact that updates to a given object must be applied sequentially.
|
||||
|
||||
Code-is-law vs. existing legal systems
|
||||
--------------------------------------
|
||||
Financial institutions need the ability to resolve conflicts using the traditional legal system where required. Corda
|
||||
is designed to make this possible by:
|
||||
|
||||
* Having permissioned networks, meaning that participants are aware of who they are dealing with in every single
|
||||
transaction
|
||||
* All code contracts are backed by a legal document describing the contract's intended behavior which can be relied
|
||||
upon to resolve conflicts
|
||||
|
||||
Build vs. re-use
|
||||
----------------
|
||||
Wherever possible, Corda re-uses existing technologies to make the platform more robust platform overall. For
|
||||
example, Corda re-uses:
|
||||
|
||||
* Standard JVM programming languages for the development of CorDapps
|
||||
* Existing SQL databases
|
||||
* Existing message queue implementations
|
148
docs/source/key-concepts-transactions.rst
Normal file
@ -0,0 +1,148 @@
|
||||
Transactions
|
||||
============
|
||||
|
||||
.. topic:: Summary
|
||||
|
||||
* *Transactions are proposals to update the ledger*
|
||||
* *A transaction proposal will only be committed if:*
|
||||
|
||||
* *It doesn't contain double-spends*
|
||||
* *It is contractually valid*
|
||||
* *It is signed by the required parties*
|
||||
|
||||
Corda uses a *UTXO* (unspent transaction output) model where every state on the ledger is immutable. The ledger
|
||||
evolves over time by applying *transactions*, which update the ledger by marking zero or more existing ledger states
|
||||
as historic (the *inputs*) and producing zero or more new ledger states (the *outputs*). Transactions represent a
|
||||
single link in the state sequences seen in :doc:`key-concepts-states`.
|
||||
|
||||
Here is an example of an update transaction, with two inputs and two outputs:
|
||||
|
||||
.. image:: resources/basic-tx.png
|
||||
|
||||
A transaction can contain any number of inputs and outputs of any type:
|
||||
|
||||
* They can include many different state types (e.g. both cash and bonds)
|
||||
* They can be issuances (have zero inputs) or exits (have zero outputs)
|
||||
* They can merge or split fungible assets (e.g. combining a $2 state and a $5 state into a $7 cash state)
|
||||
|
||||
Transactions are *atomic*: either all the transaction's proposed changes are accepted, or none are.
|
||||
|
||||
There are two basic types of transactions:
|
||||
|
||||
* Notary-change transactions (used to change a state's notary - see :doc:`key-concepts-notaries`)
|
||||
* General transactions (used for everything else)
|
||||
|
||||
Transaction chains
|
||||
------------------
|
||||
When creating a new transaction, the output states that the transaction will propose do not exist yet, and must
|
||||
therefore be created by the proposer(s) of the transaction. However, the input states already exist as the outputs of
|
||||
previous transactions. We therefore include them in the proposed transaction by reference.
|
||||
|
||||
These input states references are a combination of:
|
||||
|
||||
* The hash of the transaction that created the input
|
||||
* The input's index in the outputs of the previous transaction
|
||||
|
||||
This situation can be illustrated as follows:
|
||||
|
||||
.. image:: resources/tx-chain.png
|
||||
|
||||
These input state references link together transactions over time, forming what is known as a *transaction chain*.
|
||||
|
||||
Committing transactions
|
||||
-----------------------
|
||||
Initially, a transaction is just a **proposal** to update the ledger. It represents the future state of the ledger
|
||||
that is desired by the transaction builder(s):
|
||||
|
||||
.. image:: resources/uncommitted_tx.png
|
||||
|
||||
To become reality, the transaction must receive signatures from all of the *required signers* (see **Commands**, below). Each
|
||||
required signer appends their signature to the transaction to indicate that they approve the proposal:
|
||||
|
||||
.. image:: resources/tx_with_sigs.png
|
||||
|
||||
If all of the required signatures are gathered, the transaction becomes committed:
|
||||
|
||||
.. image:: resources/committed_tx.png
|
||||
|
||||
This means that:
|
||||
|
||||
* The transaction's inputs are marked as historic, and cannot be used in any future transactions
|
||||
* The transaction's outputs become part of the current state of the ledger
|
||||
|
||||
Transaction validity
|
||||
--------------------
|
||||
Each required signers should only sign the transaction if the following two conditions hold:
|
||||
|
||||
* **Transaction validity**: For both the proposed transaction, and every transaction in the chain of transactions
|
||||
that created the current proposed transaction's inputs:
|
||||
* The transaction is digitally signed by all the required parties
|
||||
* The transaction is *contractually valid* (see :doc:`key-concepts-contracts`)
|
||||
* **Transaction uniqueness**: There exists no other committed transaction that has consumed any of the inputs to
|
||||
our proposed transaction (see :doc:`key-concepts-consensus`)
|
||||
|
||||
If the transaction gathers all the required signatures but these conditions do not hold, the transaction's outputs
|
||||
will not be valid, and will not be accepted as inputs to subsequent transactions.
|
||||
|
||||
Other transaction components
|
||||
----------------------------
|
||||
As well as input states and output states, transactions may contain:
|
||||
|
||||
* Commands
|
||||
* Attachments
|
||||
* Timestamps
|
||||
|
||||
For example, a transaction where Alice pays off £5 of an IOU with Bob using a £5 cash payment, supported by two
|
||||
attachments and a timestamp, may look as follows:
|
||||
|
||||
.. image:: resources/full-tx.png
|
||||
|
||||
We explore the role played by the remaining transaction components below.
|
||||
|
||||
Commands
|
||||
^^^^^^^^
|
||||
Suppose we have a transaction with a cash state and a bond state as inputs, and a cash state and a bond state as
|
||||
outputs. This transaction could represent two different scenarios:
|
||||
|
||||
* A bond purchase
|
||||
* A coupon payment on a bond
|
||||
|
||||
We can imagine that we'd want to impose different rules on what constitutes a valid transaction depending on whether
|
||||
this is a purchase or a coupon payment. For example, in the case of a purchase, we would require a change in the bond's
|
||||
current owner, whereas in the case of a coupon payment, we would require that the ownership of the bond does not
|
||||
change.
|
||||
|
||||
For this, we have *commands*. Including a command in a transaction allows us to indicate the transaction's intent,
|
||||
affecting how we check the validity of the transaction.
|
||||
|
||||
Each command is also associated with a list of one or more *signers*. By taking the union of all the public keys
|
||||
listed in the commands, we get the list of the transaction's required signers. In our example, we might imagine that:
|
||||
|
||||
* In a coupon payment on a bond, only the owner of the bond is required to sign
|
||||
* In a cash payment, only the owner of the cash is required to sign
|
||||
|
||||
We can visualize this situation as follows:
|
||||
|
||||
.. image:: resources/commands.png
|
||||
|
||||
Attachments
|
||||
^^^^^^^^^^^
|
||||
Sometimes, we have a large piece of data that can be reused across many different transactions. Some examples:
|
||||
|
||||
* A calendar of public holidays
|
||||
* Supporting legal documentation
|
||||
* A table of currency codes
|
||||
|
||||
For this use case, we have *attachments*. Each transaction can refer to zero or more attachments by hash. These
|
||||
attachments are ZIP/JAR files containing arbitrary content. The information in these files can then be
|
||||
used when checking the transaction's validity.
|
||||
|
||||
Time-windows
|
||||
^^^^^^^^^^^^
|
||||
In some cases, we want a transaction proposed to only be approved during a certain time-window. For example:
|
||||
|
||||
* An option can only be exercised after a certain date
|
||||
* A bond may only be redeemed before its expiry date
|
||||
|
||||
In such cases, we can add a *time-window* to the transaction. Time-windows specify the time window during which the
|
||||
transaction can be committed. We discuss time-windows in the section on :doc:`key-concepts-time-windows`.
|
@ -1,14 +1,108 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
This section describes the key concepts and features of the Corda platform.
|
||||
This section describes the key concepts and features of the Corda platform. It is intended for readers who are new to
|
||||
Corda, and want to understand its architecture. It does not contain any code, and is suitable for non-developers.
|
||||
|
||||
This section should be read in order:
|
||||
|
||||
* :doc:`key-concepts-ecosystem`
|
||||
* :doc:`key-concepts-ledger`
|
||||
* :doc:`key-concepts-states`
|
||||
* :doc:`key-concepts-contracts`
|
||||
* :doc:`key-concepts-transactions`
|
||||
* :doc:`key-concepts-flows`
|
||||
* :doc:`key-concepts-consensus`
|
||||
* :doc:`key-concepts-notaries`
|
||||
* :doc:`key-concepts-time-windows`
|
||||
* :doc:`key-concepts-oracles`
|
||||
* :doc:`key-concepts-node`
|
||||
* :doc:`key-concepts-tradeoffs`
|
||||
|
||||
The detailed thinking and rationale behind these concepts are presented in two white papers:
|
||||
|
||||
* `Corda: An Introduction`_
|
||||
* `Corda: A Distributed Ledger`_ (A.K.A. the Technical White Paper)
|
||||
|
||||
Explanations of the key concepts are also available as `videos <https://vimeo.com/album/4555732/>`_.
|
||||
Explanations of the key concepts are also available as `videos <https://vimeo.com/album/4555732/>`_:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<p><a href="https://vimeo.com/213812040">The Corda Ledger</a></p>
|
||||
<iframe src="https://player.vimeo.com/video/213812040" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p></p>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<p><a href="https://vimeo.com/213812054">States</a></p>
|
||||
<iframe src="https://player.vimeo.com/video/213812054" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p></p>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<p><a href="https://vimeo.com/213879807">Transactions</a></p>
|
||||
<iframe src="https://player.vimeo.com/video/213879807" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p></p>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<p><a href="https://vimeo.com/214168839">Contracts</a></p>
|
||||
<iframe src="https://player.vimeo.com/video/214168839" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p></p>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<p><a href="https://vimeo.com/213879293">Legal Prose</a></p>
|
||||
<iframe src="https://player.vimeo.com/video/213879293" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p></p>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<p><a href="https://vimeo.com/213881538">Commands</a></p>
|
||||
<iframe src="https://player.vimeo.com/video/213881538" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p></p>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<p><a href="https://vimeo.com/213879314">Timestamps</a></p>
|
||||
<iframe src="https://player.vimeo.com/video/213879314" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p></p>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<p><a href="https://vimeo.com/213879328">Attachments</a></p>
|
||||
<iframe src="https://player.vimeo.com/video/213879328" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p></p>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<p><a href="https://vimeo.com/214046145">Flows</a></p>
|
||||
<iframe src="https://player.vimeo.com/video/214046145" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p></p>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<p><a href="https://vimeo.com/214138438">Consensus</a></p>
|
||||
<iframe src="https://player.vimeo.com/video/214138438" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p></p>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<p><a href="https://vimeo.com/214138458">Notaries</a></p>
|
||||
<iframe src="https://player.vimeo.com/video/214138458" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p></p>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<p><a href="https://vimeo.com/214157956">Oracles</a></p>
|
||||
<iframe src="https://player.vimeo.com/video/214157956" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p></p>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<p><a href="https://vimeo.com/214168860">Corda Node, CorDapps and Network</a></p>
|
||||
<iframe src="https://player.vimeo.com/video/214168860" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p></p>
|
||||
|
||||
.. _`Corda: An Introduction`: _static/corda-introductory-whitepaper.pdf
|
||||
.. _`Corda: A Distributed Ledger`: _static/corda-technical-whitepaper.pdf
|
||||
|
@ -1,5 +1,5 @@
|
||||
Brief introduction to the node services
|
||||
=======================================
|
||||
Node services
|
||||
=============
|
||||
|
||||
This document is intended as a very brief introduction to the current
|
||||
service components inside the node. Whilst not at all exhaustive it is
|
||||
|
@ -171,7 +171,7 @@ Let's see what parameters we pass to the constructor of this oracle.
|
||||
class Oracle(val identity: Party, private val signingKey: PublicKey, val clock: Clock) = TODO()
|
||||
|
||||
Here we see the oracle needs to have its own identity, so it can check which transaction commands it is expected to
|
||||
sign for, and also needs the PublicKey portion of its signing key. Later this PublicKey will be passed to the KeyManagementService
|
||||
sign for, and also needs the PublicKey portion of its signing key. Later this PublicKey will be passed to the KeyManagementService
|
||||
to identify the internal PrivateKey used for transaction signing.
|
||||
The clock is used for the deadline functionality which we will not discuss further here.
|
||||
|
||||
@ -200,7 +200,7 @@ Binding to the network
|
||||
|
||||
.. note:: Before reading any further, we advise that you understand the concept of flows and how to write them and use
|
||||
them. See :doc:`flow-state-machines`. Likewise some understanding of Cordapps, plugins and services will be helpful.
|
||||
See :doc:`creating-a-cordapp`.
|
||||
See :doc:`running-a-node`.
|
||||
|
||||
The first step is to create the oracle as a service by annotating its class with ``@CordaService``. Let's see how that's
|
||||
done:
|
||||
|
@ -1,4 +1,4 @@
|
||||
Out of process verification
|
||||
Out-of-process verification
|
||||
===========================
|
||||
|
||||
A Corda node does transaction verification through ``ServiceHub.transactionVerifierService``. This is by default an
|
||||
|
BIN
docs/source/resources/basic-tx.png
Normal file
After Width: | Height: | Size: 145 KiB |
BIN
docs/source/resources/commands.png
Normal file
After Width: | Height: | Size: 322 KiB |
BIN
docs/source/resources/committed_tx.png
Normal file
After Width: | Height: | Size: 152 KiB |
BIN
docs/source/resources/flow-overview.png
Normal file
After Width: | Height: | Size: 364 KiB |
BIN
docs/source/resources/flow.gif
Normal file
After Width: | Height: | Size: 246 KiB |
Before Width: | Height: | Size: 220 KiB |
BIN
docs/source/resources/full-tx.png
Normal file
After Width: | Height: | Size: 294 KiB |
BIN
docs/source/resources/grouped-tx.png
Normal file
After Width: | Height: | Size: 140 KiB |
BIN
docs/source/resources/in-out-groups.png
Normal file
After Width: | Height: | Size: 195 KiB |
BIN
docs/source/resources/ledger-table.png
Normal file
After Width: | Height: | Size: 224 KiB |
BIN
docs/source/resources/ledger-venn.png
Normal file
After Width: | Height: | Size: 297 KiB |
BIN
docs/source/resources/network.png
Normal file
After Width: | Height: | Size: 285 KiB |
BIN
docs/source/resources/node-architecture.png
Normal file
After Width: | Height: | Size: 363 KiB |
BIN
docs/source/resources/node-diagram.png
Normal file
After Width: | Height: | Size: 380 KiB |
BIN
docs/source/resources/state-hierarchy.png
Normal file
After Width: | Height: | Size: 178 KiB |
BIN
docs/source/resources/state-sequence.png
Normal file
After Width: | Height: | Size: 355 KiB |
BIN
docs/source/resources/state.png
Normal file
After Width: | Height: | Size: 257 KiB |
BIN
docs/source/resources/time-window.gif
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
docs/source/resources/transaction-flow.png
Normal file
After Width: | Height: | Size: 287 KiB |
BIN
docs/source/resources/tx-chain.png
Normal file
After Width: | Height: | Size: 276 KiB |
BIN
docs/source/resources/tx-validation.png
Normal file
After Width: | Height: | Size: 153 KiB |
BIN
docs/source/resources/tx_with_sigs.png
Normal file
After Width: | Height: | Size: 113 KiB |
BIN
docs/source/resources/uncommitted_tx.png
Normal file
After Width: | Height: | Size: 111 KiB |
BIN
docs/source/resources/ungrouped-tx.png
Normal file
After Width: | Height: | Size: 135 KiB |
BIN
docs/source/resources/uniqueness-consensus.png
Normal file
After Width: | Height: | Size: 228 KiB |
BIN
docs/source/resources/validation-consensus.png
Normal file
After Width: | Height: | Size: 339 KiB |
BIN
docs/source/resources/vault-simple.png
Normal file
After Width: | Height: | Size: 470 KiB |
@ -1,52 +1,12 @@
|
||||
CorDapp basics
|
||||
Running a node
|
||||
==============
|
||||
|
||||
A CorDapp is an application that runs on the Corda platform using the platform APIs and plugin system. They are self
|
||||
contained in separate JARs from the node server JAR that are created and distributed.
|
||||
Deploying your node
|
||||
-------------------
|
||||
|
||||
App plugins
|
||||
-----------
|
||||
|
||||
.. note:: Currently apps are only supported for JVM languages.
|
||||
|
||||
To create an app plugin you must extend from `CordaPluginRegistry`_. The JavaDoc contains
|
||||
specific details of the implementation, but you can extend the server in the following ways:
|
||||
|
||||
1. Register your flows and services (see below).
|
||||
2. Web APIs: You may register your own endpoints under /api/ of the bundled web server.
|
||||
3. Static web endpoints: You may register your own static serving directories for serving web content from the web server.
|
||||
4. Whitelisting your additional contract, state and other classes for object serialization. Any class that forms part
|
||||
of a persisted state, that is used in messaging between flows or in RPC needs to be whitelisted.
|
||||
|
||||
Flows and services
|
||||
------------------
|
||||
|
||||
Flows are of two types: initiating and initiated. Initiating flows need to be annotated with ``@InitiatingFlow`` and can
|
||||
be started in one of three ways:
|
||||
|
||||
1. By a user of your CorDapp via RPC in which the flow also needs to be annotated with ``@StartableByRPC``.
|
||||
2. By another CorDapp executing it as a sub-flow in their own flow.
|
||||
3. By a ``SchedulableState`` activity event, in which the flow also needs to be annotated with ``@SchedulableFlow``
|
||||
|
||||
``InitiatingFlow`` also has a ``version`` property to enable you to version your flows. A node will only accept communication
|
||||
from an initiating party if the version numbers match up.
|
||||
|
||||
Initiated flows are typically private to your CorDapp and need to be annotated with ``@InitiatedBy`` which point to
|
||||
initiating flow Class. The node scans your CorDapps for these annotations and automatically registers the initiating to
|
||||
initiated mapping for you.
|
||||
|
||||
If your CorDapp also needs to have additional services running in the node, such as oracles, then annotate your service
|
||||
class with ``@CordaService``. As with the flows, the node will automatically register it and make it available for use by
|
||||
your flows. The service class has to implement ``SerializeAsToken`` to ensure they work correctly within flows. If possible
|
||||
extend ``SingletonSerializeAsToken`` instead to avoid the boilerplate.
|
||||
|
||||
Starting nodes
|
||||
--------------
|
||||
|
||||
To use an app you must also have a node server. To create a node server run the ``gradle deployNodes`` task.
|
||||
|
||||
This will output the node JAR to ``build/libs/corda.jar`` and several sample/standard
|
||||
node setups to ``build/nodes``. For now you can use the ``build/nodes/nodea`` configuration as a template.
|
||||
You deploy a node by running the ``gradle deployNodes`` task. This will output the node JAR to
|
||||
``build/libs/corda.jar`` and several sample/standard node setups to ``build/nodes``. For now you can use the
|
||||
``build/nodes/nodea`` configuration as a template.
|
||||
|
||||
Each node server by default must have a ``node.conf`` file in the current working directory. After first
|
||||
execution of the node server there will be many other configuration and persistence files created in this
|
||||
@ -58,14 +18,6 @@ workspace directory. The directory can be overridden by the ``--base-directory=<
|
||||
temporary folder. It is therefore suggested that the CAPSULE_CACHE_DIR environment variable be set before
|
||||
starting the process to control this location.
|
||||
|
||||
Installing apps
|
||||
---------------
|
||||
|
||||
Once you have created your app JAR you can install it to a node by adding it to ``<node_dir>/plugins/``. In this
|
||||
case the ``node_dir`` is the location where your node server's JAR and configuration file is.
|
||||
|
||||
.. note:: If the directory does not exist you can create it manually.
|
||||
|
||||
Starting your node
|
||||
------------------
|
||||
|
@ -1,7 +1,8 @@
|
||||
Running the demos
|
||||
=================
|
||||
|
||||
The Corda repository contains a number of demo programs demonstrating the functionality developed so far:
|
||||
The `Corda repository <https://github.com/corda/corda>`_ contains a number of demo programs demonstrating
|
||||
Corda's functionality:
|
||||
|
||||
1. The Trader Demo, which shows a delivery-vs-payment atomic swap of commercial paper for cash
|
||||
2. The IRS Demo, which shows two nodes establishing an interest rate swap and performing fixings with a
|
||||
|
@ -33,7 +33,8 @@ allowed to do anything! Things to watch out for:
|
||||
sides of the flow.
|
||||
|
||||
The theme should be clear: signing is a very sensitive operation, so you need to be sure you know what it is you
|
||||
are about to sign, and that nothing has changed in the small print!
|
||||
are about to sign, and that nothing has changed in the small print! Once you have provided your signature over a
|
||||
transaction to a counterparty, there is no longer anything you can do to prevent them from committing it to the ledger.
|
||||
|
||||
Contracts
|
||||
---------
|
||||
|
@ -1,4 +1,4 @@
|
||||
Object Serialization
|
||||
Object serialization
|
||||
====================
|
||||
|
||||
What is serialization (and deserialization)?
|
||||
@ -23,7 +23,7 @@ Classes get onto the whitelist via one of three mechanisms:
|
||||
class itself, on any of the super classes or on any interface implemented by the class or super classes or any
|
||||
interface extended by an interface implemented by the class or superclasses.
|
||||
#. By returning the class as part of a plugin via the method ``customizeSerialization``. It's important to return
|
||||
true from this method if you override it, otherwise the plugin will be excluded. See :doc:`corda-plugins`.
|
||||
true from this method if you override it, otherwise the plugin will be excluded. See :doc:`writing-cordapps`.
|
||||
#. Via the built in Corda whitelist (see the class ``DefaultWhitelist``). Whilst this is not user editable, it does list
|
||||
common JDK classes that have been whitelisted for your convenience.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
.. _log4j2: http://logging.apache.org/log4j/2.x/
|
||||
|
||||
What is a Corda network?
|
||||
Creating a Corda network
|
||||
========================
|
||||
|
||||
A Corda network consists of a number of machines running nodes, including a single node operating as the network map
|
||||
|
@ -1,7 +1,7 @@
|
||||
.. _graphstream: http://graphstream-project.org/
|
||||
|
||||
Client RPC API tutorial
|
||||
=======================
|
||||
Using the client RPC API
|
||||
========================
|
||||
|
||||
In this tutorial we will build a simple command line utility that connects to a node, creates some Cash transactions and
|
||||
meanwhile dumps the transaction graph to the standard output. We will then put some simple visualisation on top. For an
|
||||
@ -104,7 +104,7 @@ requests or responses with the Corda node. Here's an example of both ways you c
|
||||
:start-after: START 7
|
||||
:end-before: END 7
|
||||
|
||||
See more on plugins in :doc:`creating-a-cordapp`.
|
||||
See more on plugins in :doc:`running-a-node`.
|
||||
|
||||
.. warning:: We will be replacing the use of Kryo in the serialization framework and so additional changes here are likely.
|
||||
|
||||
@ -162,4 +162,4 @@ With regards to the start flow RPCs, there is an extra layer of security whereby
|
||||
annotated with ``@StartableByRPC``. Flows without this annotation cannot execute using RPC.
|
||||
|
||||
See more on security in :doc:`secure-coding-guidelines`, node configuration in :doc:`corda-configuration-file` and
|
||||
Cordformation in :doc:`creating-a-cordapp`
|
||||
Cordformation in :doc:`running-a-node`.
|
||||
|
@ -214,7 +214,7 @@ We have four fields in our state:
|
||||
relationships such as a derivative contract.
|
||||
* ``faceValue``, an ``Amount<Issued<Currency>>``, which wraps an integer number of pennies and a currency that is
|
||||
specific to some issuer (e.g. a regular bank, a central bank, etc). You can read more about this very common
|
||||
type in :doc:`key-concepts-core-types`.
|
||||
type in :doc:`api-core-types`.
|
||||
* ``maturityDate``, an `Instant <https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html>`_, which is a type
|
||||
from the Java 8 standard time library. It defines a point on the timeline.
|
||||
|
||||
@ -641,7 +641,7 @@ any ``StateAndRef`` (input), ``ContractState`` (output) or ``Command`` objects a
|
||||
for you.
|
||||
|
||||
There's one final thing to be aware of: we ask the caller to select a *notary* that controls this state and
|
||||
prevents it from being double spent. You can learn more about this topic in the :doc:`key-concepts-consensus-notaries` article.
|
||||
prevents it from being double spent. You can learn more about this topic in the :doc:`key-concepts-notaries` article.
|
||||
|
||||
.. note:: For now, don't worry about how to pick a notary. More infrastructure will come later to automate this
|
||||
decision for you.
|
||||
|
137
docs/source/writing-cordapps.rst
Normal file
@ -0,0 +1,137 @@
|
||||
Writing a CorDapp
|
||||
=================
|
||||
|
||||
The source-code for a CorDapp is a set of files written in a JVM language that defines a set of Corda components:
|
||||
|
||||
* States (i.e. classes implementing ``ContractState``)
|
||||
* Contracts (i.e. classes implementing ``Contract``)
|
||||
* Flows (i.e. classes extending ``FlowLogic``)
|
||||
* Web APIs
|
||||
* Services
|
||||
|
||||
These files should be placed under ``src/main/[java|kotlin]``. The CorDapp's resources folder (``src/main/resources``)
|
||||
should also include the following subfolders:
|
||||
|
||||
* ``src/main/resources/certificates``, containing the node's certificates
|
||||
* ``src/main/resources/META-INF/services``, containing a file named ``net.corda.core.node.CordaPluginRegistry``
|
||||
|
||||
For example, the source-code of the `Template CorDapp <https://github.com/corda/cordapp-template>`_ has the following
|
||||
structure:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
src
|
||||
├── main
|
||||
│ ├── java
|
||||
│ │ └── com
|
||||
│ │ └── template
|
||||
│ │ ├── Main.java
|
||||
│ │ ├── api
|
||||
│ │ │ └── TemplateApi.java
|
||||
│ │ ├── client
|
||||
│ │ │ └── TemplateClientRPC.java
|
||||
│ │ ├── contract
|
||||
│ │ │ └── TemplateContract.java
|
||||
│ │ ├── flow
|
||||
│ │ │ └── TemplateFlow.java
|
||||
│ │ ├── plugin
|
||||
│ │ │ └── TemplatePlugin.java
|
||||
│ │ ├── service
|
||||
│ │ │ └── TemplateService.java
|
||||
│ │ └── state
|
||||
│ │ └── TemplateState.java
|
||||
│ └── resources
|
||||
│ ├── META-INF
|
||||
│ │ └── services
|
||||
│ │ └── net.corda.core.node.CordaPluginRegistry
|
||||
│ ├── certificates
|
||||
│ │ ├── sslkeystore.jks
|
||||
│ │ └── truststore.jks
|
||||
│ └──templateWeb
|
||||
│ ├── index.html
|
||||
│ └── js
|
||||
│ └── template-js.js
|
||||
└── test
|
||||
└── java
|
||||
└── com
|
||||
└── template
|
||||
└── contract
|
||||
└── TemplateTests.java
|
||||
|
||||
Defining a plugin
|
||||
-----------------
|
||||
You can specify the web APIs and static web content for your CorDapp by subclassing
|
||||
``net.corda.core.node.CordaPluginRegistry``:
|
||||
|
||||
* The ``webApis`` property is a list of JAX-RS annotated REST access classes. These classes will be constructed by
|
||||
the bundled web server and must have a single argument constructor taking a ``CordaRPCOps`` object. This will
|
||||
allow the API to communicate with the node process via the RPC interface. These web APIs will not be available if the
|
||||
bundled web server is not started.
|
||||
|
||||
* The ``staticServeDirs`` property maps static web content to virtual paths and allows simple web demos to be
|
||||
distributed within the CorDapp jars. These static serving directories will not be available if the bundled web server
|
||||
is not started.
|
||||
* The static web content itself should be placed inside the ``src/main/resources`` directory
|
||||
|
||||
* The ``customizeSerialization`` function allows classes to be whitelisted for object serialisation, over and
|
||||
above those tagged with the ``@CordaSerializable`` annotation. For instance, new state types will need to be
|
||||
explicitly registered. In general, the annotation should be preferred. See :doc:`serialization`.
|
||||
|
||||
The fully-qualified class path of each ``CordaPluginRegistry`` subclass must be added to the
|
||||
``net.corda.core.node.CordaPluginRegistry`` file in the CorDapp's ``resources/META-INF/services`` folder. A CorDapp
|
||||
can register multiple plugins in a single ``net.corda.core.node.CordaPluginRegistry`` file.
|
||||
|
||||
Installing CorDapps
|
||||
-------------------
|
||||
To run a CorDapp, its source is compiled into a JAR by running the gradle ``jar`` task. The CorDapp JAR is then added
|
||||
to a node by adding it to the node's ``<node_dir>/plugins/`` folder (where ``node_dir`` is the folder in which the
|
||||
node's JAR and configuration files are stored).
|
||||
|
||||
.. note:: Any external dependencies of your CorDapp will automatically be placed into the
|
||||
``<node_dir>/dependencies/`` folder. This will be changed in a future release.
|
||||
|
||||
.. note:: Building nodes using the gradle ``deployNodes`` task will place the CorDapp JAR into each node's ``plugins``
|
||||
folder automatically.
|
||||
|
||||
At runtime, nodes will load any plugins present in their ``plugins`` folder.
|
||||
|
||||
RPC permissions
|
||||
---------------
|
||||
If a node's owner needs to interact with their node via RPC (e.g. to read the contents of the node's storage), they
|
||||
must define one or more RPC users. These users are added to the node's ``node.conf`` file.
|
||||
|
||||
The syntax for adding an RPC user is:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: groovy
|
||||
|
||||
rpcUsers=[
|
||||
{
|
||||
username=exampleUser
|
||||
password=examplePass
|
||||
permissions=[]
|
||||
}
|
||||
...
|
||||
]
|
||||
|
||||
Currently, users need special permissions to start flows via RPC. These permissions are added as follows:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: groovy
|
||||
|
||||
rpcUsers=[
|
||||
{
|
||||
username=exampleUser
|
||||
password=examplePass
|
||||
permissions=[
|
||||
"StartFlow.net.corda.flows.ExampleFlow1",
|
||||
"StartFlow.net.corda.flows.ExampleFlow2"
|
||||
]
|
||||
}
|
||||
...
|
||||
]
|
||||
|
||||
.. note:: Currently, the node's web server has super-user access, meaning that it can run any RPC operation without
|
||||
logging in. This will be changed in a future release.
|
@ -54,7 +54,9 @@ class Cash : OnLedgerAsset<Currency, Cash.Commands, Cash.State>() {
|
||||
* to evolve without requiring code changes. But creates a risk that users create objects governed by a program
|
||||
* that is inconsistent with the legal contract.
|
||||
*/
|
||||
// DOCSTART 2
|
||||
override val legalContractReference: SecureHash = SecureHash.sha256("https://www.big-book-of-banking-law.gov/cash-claims.html")
|
||||
// DOCEND 2
|
||||
override fun extractCommands(commands: Collection<AuthenticatedObject<CommandData>>): List<AuthenticatedObject<Cash.Commands>>
|
||||
= commands.select<Cash.Commands>()
|
||||
|
||||
@ -81,6 +83,7 @@ class Cash : OnLedgerAsset<Currency, Cash.Commands, Cash.State>() {
|
||||
class ConserveAmount : AbstractConserveAmount<State, Commands, Currency>()
|
||||
}
|
||||
|
||||
// DOCSTART 1
|
||||
/** A state representing a cash claim against some party. */
|
||||
data class State(
|
||||
override val amount: Amount<Issued<Currency>>,
|
||||
@ -119,6 +122,7 @@ class Cash : OnLedgerAsset<Currency, Cash.Commands, Cash.State>() {
|
||||
/** Object Relational Mapping support. */
|
||||
override fun supportedSchemas(): Iterable<MappedSchema> = listOf(CashSchemaV1)
|
||||
}
|
||||
// DOCEND 1
|
||||
|
||||
// Just for grouping
|
||||
interface Commands : FungibleAsset.Commands {
|
||||
|
@ -1 +1 @@
|
||||
Please refer to the documentation in <corda-root>/doc/build/html/creating-a-cordapp.html#cordformation.
|
||||
Please refer to the documentation in <corda-root>/doc/build/html/running-a-node.html#cordformation.
|
@ -183,7 +183,7 @@ private fun lookupMachineNameAndMaybeWarn(): String {
|
||||
// Also see https://bugs.openjdk.java.net/browse/JDK-8143378
|
||||
val messages = listOf(
|
||||
"Your computer took over a second to resolve localhost due an incorrect configuration. Corda will work but start very slowly until this is fixed. ",
|
||||
"Please see https://docs.corda.net/getting-set-up-fault-finding.html#slow-localhost-resolution for information on how to fix this. ",
|
||||
"Please see https://docs.corda.net/troubleshooting.html#slow-localhost-resolution for information on how to fix this. ",
|
||||
"It will only take a few seconds for you to resolve."
|
||||
)
|
||||
log.warn(messages.joinToString(""))
|
||||
|