Documentation Index
Fetch the complete documentation index at: https://docs.canton.network/llms.txt
Use this file to discover all available pages before exploring further.
Causality
Daml ledgers do not totally order all transactions. So different parties may observe two transactions on different Participant Nodes in different orders via the gRPC Ledger API. Moreover, different Participant Nodes may output two transactions for the same party in different orders. This document explains the ordering guarantees that Daml ledgers do provide, by example and formally via the concept of causality graphs and local ledgers. The presentation assumes that you are familiar with the following concepts:- The Ledger API
- The Daml Ledger Model
Causality Examples
A Daml Ledger need not totally order all transaction, unlike ledgers in the Daml Ledger Model. The following examples illustrate these ordering guarantees of the Ledger API. They are based on the paint counteroffer workflow from the Daml Ledger Model’s privacy section, ignoring the total ordering coming from the Daml Ledger Model. Recall that the party projections are as follows.Stakeholders of a Contract See Creation and Archival in the Same Order
Every Daml Ledger orders the creation of theCounterOffer A P Bank before the painter exercising the consuming choice on the CounterOffer. (If the Create was ordered after the Exercise, the resulting shared ledger would be inconsistent, which violates the validity guarantee of Daml ledgers.) Accordingly, Alice will see the creation before the archival on her transaction stream and so will the painter. This does not depend on whether they are hosted on the same Participant Node.
Signatories of a Contract and Stakeholder Actors See Usages After the Creation and Before the Archival
TheFetch A (Iou Bank A) action comes after the creation of the Iou Bank A and before its archival, for both Alice and the Bank, because the Bank is a signatory of the Iou Bank A contract and Alice is a stakeholder of the Iou Bank A contract and an actor on the Fetch action.
Commits Are Atomic
Alice sees the Create of herIou before the creation of the CounterOffer, because the CounterOffer is created in the same commit as the Fetch of the Iou and the Fetch commit comes after the Create of the Iou.
Non-Consuming Usages in Different Commits May Appear in Different Orders
Suppose that the Bank exercises a non-consuming choice on theIou Bank A without consequences while Alice creates the CounterOffer. In the ledger shown below, the Bank’s commit comes before Alice’s commit.
Iou. Yet, the Fetch may come before the non-consuming Exercise in the Bank’s transaction tree stream.
Out-of-Band Causality Is Not Respected
The following examples assume that Alice splits up her commit into two as follows: Alice can specify in theCounterOffer the Iou that she wants to pay the painter with. In a deployed implementation, Alice’s application first observes the created Iou contract via the Update Service or State Service before she requests to create the CounterOffer. Such application logic does not induce an ordering between commits. So the creation of the CounterOffer need not come after the creation of the Iou.
If Alice is hosted on several Participant Nodes, the Participant Nodes can therefore output the two creations in either order.
The rationale for this behaviour is that Alice could have learnt about the contract ID out of band or made it up. The Participant Nodes therefore cannot know whether there will ever be a Create event for the contract. So if Participant Nodes delayed outputting the Create action for the CounterOffer until a Create event for the Iou contract was published, this delay might last forever and liveness is lost. Daml ledgers therefore do not capture data flow through applications.
Divulged Actions Do Not Induce Order
The painter witnesses the fetching of Alice’sIou when the ShowIou contract is consumed. The painter also witnesses the Exercise of the Iou when Alice exercises the transfer choice as a consequence of the painter accepting the CounterOffer. However, as the painter is not a stakeholder of Alice’s Iou contract, he may observe Alice’s ShowIou commit after the archival of the Iou as part of accepting the CounterOffer.
In practice, this can happen in a setup where two Participant Nodes N``1 and N``2 host the painter. He sees the divulged Iou and the created CounterOffer through N``1’s transaction tree stream and then submits the acceptance through N``1. Like in the previous example, N``2 does not know about the dependence of the two commits. Accordingly, N``2 may output the accepting transaction before the ShowIou contract on the transaction stream.
Even though this may seem unexpected, it is in line with stakeholder-based ledgers: Since the painter is not a stakeholder of the Iou contract, he should not care about the archivals or creates of the contract. In fact, the divulged Iou contract shows up neither in the painter’s State Service nor in the ACS delta in the update stream. Such witnessed events are included in the transaction tree stream as a convenience: They relieve the painter from computing the consequences of the choice and enable him to check that the action conforms to the Daml model.
Similarly, being an actor of an Exercise action induces order with respect to other uses of the contract only if the actor is a contract stakeholder. This is because non-stakeholder actors of an Exercise action merely authorize the action, but they do not track whether the contract is active; this is what signatories and contract observers are for. Analogously, choice observers of an Exercise action benefit from the ordering guarantees only if they are contract stakeholders.
The Ordering Guarantees Depend on the Party
By the previous example, for the painter, fetching theIou is not ordered before transferring the Iou. For Alice, however, the Fetch must appear before the Exercise because Alice is a stakeholder on the Iou contract. This shows that the ordering guarantees depend on the party.
Causality Graphs
The above examples indicate that Daml ledgers order transactions only partially. Daml ledgers can be represented as finite directed acyclic graphs (DAG) of transactions.Definition »causality graph«
A causality graph is a finite directed acyclic graph
G of transactions that is transitively closed. Transitively closed means that whenever v``1 -> v``2 and v``2 -> v``3 are edges in G, then there is also an edge v``1 -> v``3 in G.Definition »action order«
For a causality graph
G, the induced action order on the actions in the transactions combines the graph-induced order between transactions with the execution order of actions inside each transaction. It is the least partial order that includes the following ordering relations between two actions act``1 and act``2:-
act``1andact``2belong to the same transaction andact``1precedesact``2in the transaction. -
act``1andact``2belong to different transactions in verticestx``1andtx``2and there is a path inGfromtx``1totx``2.
Checking for an edge instead of a path in
G from tx``1 to tx``2 is equivalent because causality graphs are transitively closed. The definition uses path because the figures below omit transitive edges for readability.tx1 to tx4 is not shown. The Create action of Alice’s Iou is ordered before the Create action of the ShowIou contract because there is an edge from the transaction tx1 with the Iou Create to the transaction tx3 with the ShowIou Create. Moreover, the ShowIou Create action is ordered before the Fetch of Alice’s Iou because the Create action precedes the Fetch action in the transaction. In contrast, the Create actions of the CounterOffer and Alice’s Iou are unordered: neither precedes the other because they belong to different transaction and there is no directed path between them.
Consistency
Consistency ensures that a causality graph sufficiently orders all the transactions. It generalizes ledger consistency from the Daml Ledger Model as explained below.Definition »Causal consistency for a contract«
Let
G be a causality graph and X be a set of actions on a contract c that belong to transactions in G. The graph G is causally consistent for the contract c on X if all of the following hold:- If
Xis not empty, thenXcontains exactly one Create action. This action precedes all other actions inXinG’s action order. - If
Xcontains a consuming Exercise actionact, thenactfollows all actions inXother thanactinG’s action order.
G be a causality graph and X be a set of actions on a key k that belong to transactions in G. The graph G is causally consistent for the key k on X if all of the following hold:- All Create and consuming Exercise actions in
Xare totally ordered inG’s action order and Creates and consuming Exercises alternate, starting with Create. Every consecutive Create-Exercise pair acts on the same contract. - All NoSuchKey actions in
Xare action-ordered with respect to all Create and consuming Exercise actions inX. No NoSuchKey action is action-ordered between a Create action and its subsequent consuming Exercise action inX.
Definition »Consistency for a causality graph«
Let
When edges are added to an X be a subset of the actions in a causality graph G. Then G is consistent on X (or X-consistent) if G is causally consistent for all contracts c on the set of actions on c in X and for all keys k on the set of actions on k in X. G is consistent if G is consistent on all the actions in G.X-consistent causality graph such that it remains acyclic and transitively closed, the resulting graph is again X-consistent. So it makes sense to consider minimal consistent causality graphs.
Definition »Minimal consistent causality graph«
An
For example, the above causality graph for the split counteroffer workflow is consistent. This causality graph is minimal, as the following analysis shows:
X-consistent causality graph G is X-minimal if no strict subgraph of G (same vertices, fewer edges) is an X-consistent causality graph. If X is the set of all actions in G, then X is omitted.| Edge | Justification |
|---|---|
tx1 -> tx3 | Alice’s Iou Create action of must precede the Fetch action. |
tx2 -> tx4 | The CounterOffer Create action of must precede the Exercise action. |
tx3 -> tx4 | The consuming Exercise action on Alice’s Iou must follow the Fetch action. |
X. If X consists of the actions on Iou contracts, this causality graph is X-consistent. Yet, it is not X-minimal since the edge tx2 -> tx4 can be removed without violating X-consistency: the edge is required only because of the CounterOffer actions, which are excluded from X. The X-minimal consistent causality graph looks as follows, where the actions in X are highlighted in red.
Another example of a minimal causality graph is shown below. At the top, the transactions tx1 to tx4 create an Iou for Alice, exercise two non-consuming choices on it, and transfer the Iou to the painter. At the bottom, tx5 asserts that there is no key for an Account contract for the painter. Then, tx6 creates an such account with balance 0 and tx7 deposits the painter’s Iou from tx4 into the account, updating the balance to 1.
Iou transfer workflow with the Account creation workflow only at the end, when the Iou is deposited into the account. As will be formalized below, the Bank, Alice, and the painter therefore need not observe the transactions tx1 to tx7 in the same order.
Moreover, transaction tx2 and tx3 are unordered in this causality graph even though they act on the same Iou contract. However, as both actions are non-consuming, they do not interfere with each other and could therefore be parallelized, too. Alice and the Bank accordingly may observe them in different orders.
The NoSuchKey action in tx5 must be ordered with respect to the two Account Create actions in tx6 and tx7 and the consuming Exercise on the Account contract in tx7, by the key consistency conditions. For this set of transactions, consistency allows only one such order: tx5 comes before tx6 because tx7 is atomic: tx5 cannot be interleaved with tx7, e.g., between the consuming Exercise of the Acc Bank P P 0 and the Create of the updated account Acc Bank P P 1.
NoSuchKey actions are similar to non-consuming Exercises and Fetches of contracts when it comes to causal ordering: If there were another transaction tx5' with a NoSuchKey (Acc, Bank, P) action, then tx5 and tx5' need not be ordered, just like tx2 and tx3 are unordered.
From Causality Graphs to Ledgers
Since causality graphs are acyclic, their vertices can be sorted topologically and the resulting list is again a causality graph, where every vertex has an outgoing edge to all later vertices. If the original causality graph isX-consistent, then so is the topological sort, as topological sorting merely adds edges. For example, the transactions on the ledger in the out-of-band causality example are a topological sort of the corresponding causality graph.
Conversely, we can reduce an X-consistent causality graph to only the causal dependencies that X-consistency imposes. This gives a minimal X-consistent causality graph.
Definition »Reduction of a consistent causality graph«
For an
The causality graph for the split X-consistent causality graph G, there exists a unique minimal X-consistent causality graph reduce``X``(G) with the same vertices and the edges being a subset of G. The graph reduce``X``(G) is called the X-reduction of G. As before, X is omitted if it contains all actions in G.CounterOffer workflow is minimal and therefore its own reduction. It is also the reduction of the topological sort, i.e., the ledger in the out-of-band causality example.
The reduction
reduce``X``(G) of an X-consistent causality graph G can be computed as follows:- Set the vertices of
G'to the vertices ofG. - The causal consistency conditions for contracts and keys demand that certain pairs of actions
act``1andact``2inXmust be action-ordered. For each such pair, determine the actions’ ordering inGand add an edge toG'from the earlier action’s transaction to the later action’s transaction. reduce``X``(G)is the transitive closure ofG'.
G to the ledgers L from the Daml Ledger Model. Topological sort transforms a causality graph G into a sequence of transactions; extending them with the requesters gives a sequence of commits, i.e., a ledger in the Daml Ledger Model. Conversely, a sequence of commits L yields a causality graph G``L by taking the transactions as vertices and adding an edge from tx1 to tx2 whenever tx1’s commit precedes tx2’s commit in the sequence.
There are now two consistency definitions:
- Ledger Consistency according to Daml Ledger Model
- Consistency of causality graph
G is a consistent causality graph, then the topological sort is ledger consistent. Conversely, if the sequence of commits L is ledger consistent, G``L is a consistent causality graph, and so is the reduction reduce(G``L``).
Local Ledgers
As explained in the Daml Ledger Model, parties see only a projection of the shared ledger for privacy reasons. Like consistency, projection extends to causality graphs as follows. Definition »Stakeholder informee« A partyP is a stakeholder informee of an action act if all of the following holds:
Pis an informee ofact.- If
actis an action on a contract thenPis a stakeholder of the contract.
G is consistent for a party P (P-consistent) if G is consistent on all the actions that P is a stakeholder informee of.
The notions of X-minimality and X-reduction extend to parties accordingly.
For example, the split counteroffer causality graph without the edge tx2 -> tx4 is consistent for the Bank because the Bank is a stakeholder informee of exactly the highlighted actions. It is also minimal Bank-consistent and the Bank-reduction of the original split counteroffer causality graph.
Definition »Projection of a consistent causality graph«
The projection proj``P``(G) of a consistent causality graph G to a party P is the P-reduction of the following causality graph `G’`:
- The vertices of
G'are the vertices ofGprojected toP, excluding empty projections. - There is an edge between two vertices
v``1andv``2inG'if there is an edge from theG-vertex corresponding tov``1to theG-vertex corresponding tov``2.
Iou contracts, so the causality graph projection does not contain tx2 any more. Similarly, the painter is not aware of tx1, where Alice’s Iou is created. Moreover, there is no longer an edge from tx3 to tx4 in the painter’s local ledger. This is because the edge is induced by the Fetch of Alice’s Iou preceding the consuming Exercise. However, the painter is not an informee of those two actions; he merely witnesses the Fetch and Exercise actions as part of divulgence. Therefore no ordering is required from the painter’s point of view. This difference explains the divulgence causality example.
Ledger API Ordering Guarantees
The Update Service provides the updates as a stream of Daml transactions and the State Service summarizes all the updates up to a given point by the contracts that are active at this point. Conceptually, both services are derived from the local ledger that the Participant Node manages for each hosted party. That is, the transaction tree stream for a party is a topological sort of the party’s local ledger. The flat transaction stream contains precisely theCreatedEvents and ArchivedEvents that correspond to Create and consuming Exercise actions in transaction trees on the transaction tree stream where the party is a stakeholder of the affected contract.
The transaction trees of the Update Service omit Fetch and NoSuchKey actions that are part of the transactions in the local ledger. The Fetch and NoSuchKey actions are thus removed before the Update Service outputs the transaction trees.
The virtual shared causality graph exists only as a concept, to reason about Daml ledger guarantees. A deployed Daml ledger in general does not store or even construct such a shared causality graph. The Participant Nodes merely maintain the local ledgers for their parties. They synchronize these local ledgers to the extent that they remain consistent. That is, all the local ledgers can in theory be combined into a consistent single causality graph of which they are projections.
Explaining the Causality Examples
The causality examples can be explained in terms of causality graphs and local ledgers as follows:causality-example-create-archiveCausal consistency for the contract requires that the Create comes before the consuming Exercise action on the contract. As all stakeholders are informees on Create and consuming Exercise actions of their contracts, the stakeholder’s local ledgers impose this order on the actions.causality-example-create-use-archiveCausal consistency for the contract requires that the Create comes before the non-consuming Exercise and Fetch actions of a contract and that consuming Exercises follow them. Since signatories and stakeholder actors are informees of Create, Exercise, and Fetch actions, the stakeholder’s local ledgers impose this order on the actions.causality-example-commit-atomicLocal ledgers are DAGs of (projected) transactions. Topologically sorting such a DAG cannot interleave one transaction with another, even if the transaction consists of several top-level actions.causality-example-non-consumingCausal consistency does not require ordering between non-consuming usages of a contract. As there is no other action in the transaction that would prescribe an ordering, the Participant Nodes can output them in any order.causality-example-out-of-bandOut-of-band data flow is not captured by causal consistency and therefore does not induce ordering.causality-divulgence-exampleThe painter is not an informee of the Fetch and Exercise actions on Alice’sIou; he merely witnesses them. The painter’s local ledger therefore does not ordertx3beforetx4. So the painter’s transaction stream can outputtx4beforetx3.causality-example-depend-on-partyAlice is an informee of the Fetch and Exercise actions on herIou. Unlike for the painter, her local ledger does ordertx3beforetx4, so Alice is guaranteed to observetx3beforetx4on all Participant Nodes through which she is connect to the Daml ledger.
- Move LAPI parts to BUILD subsite
- Integrate time monotonicity into the ledger model
- WHERE SHOULD THE SKEWs go?
Time on Daml Ledgers
The Daml language contains a function getTime which returns the “current time”. However, the concept of a “current time” can be challenging in a distributed setting. This document describes the detailed semantics of time on Daml ledgers, centered around the two timestamps assigned to each transaction: the ledger timelt_TX and the record time rt_TX.
Ledger Time
The ledger timelt_TX is a property of a transaction. It is a timestamp that defines the value of all getTime calls in the given transaction, and has microsecond resolution. The ledger time is assigned by the submitting participant as part of the Daml command interpretation.
Record Time
The record timert_TX is another property of a transaction. It is a timestamp with microsecond resolution, and it is assigned by the backing storage mechanism when the transaction is persisted.
The record time should be an intuitive representation of “real time”, but the Daml abstract ledger model does not prescribe exactly how to assign the record time. Each persistence technology might use a different way of representing time in a distributed setting.
Guarantees
The ledger time of a valid transactionTX must fulfill the following rules:
- Causal monotonicity: for any action (create, exercise, fetch, lookup) in
TXon a contractC,lt_TX >= lt_C, wherelt_Cis the ledger time of the transaction that createdC. - Bounded skew:
rt_TX - skew_min <= lt_TX <= rt_TX + skew_max, whereskew_minandskew_maxare parameters defined by the ledger.
Assign Ledger Time
The ledger time is assigned automatically by the participant. In most cases, Daml applications will not need to worry about ledger time and record time at all. For reference, this section describes the details of how the ledger time is currently assigned. The algorithm is not part of the definition of time in Daml, and may change in the future.- When submitting commands over the Ledger API, users can optionally specify a
min_ledger_time_relormin_ledger_time_absargument. This defines a lower bound for the ledger time in relative and absolute terms, respectively. - The ledger time is set to the highest of the following values:
max(lt_C_1, ..., lt_C_n), the maximum ledger time of all contracts used by the given transactiont_p, the local time on the participantt_p + min_ledger_time_rel, ifmin_ledger_time_relis givenmin_ledger_time_abs, ifmin_ledger_time_absis given
- Since the set of commands used by a given transaction can depend on the chosen time, the above process might need to be repeated until a suitable ledger time is found.
- If no suitable ledger time is found after 3 iterations, the submission is rejected. This can happen if there is contention around a contract, or if the transaction uses a very fine-grained control flow based on time.
- At this point, the ledger time may lie in the future (e.g., if a large value for
min_ledger_time_relwas given). The participant waits untillt_TX - transaction_latencybefore it submits the transaction to the ledger -the intention is that the transaction is recorded atlt_TX == rt_TX.
min_ledger_time_rel and min_ledger_time_abs if you expect that command interpretation will take a considerate amount of time, such that by the time the resulting transaction is submitted to the ledger, its assigned ledger time is not valid anymore. Note that these parameters can only make sure that the transaction arrives roughly at rt_TX at the ledger. If a subsequent validation on the ledger takes longer than skew_max, the transaction will still be rejected and you’ll have to ask your ledger operator to increase the skew_max time model parameter.