Structure
This section looks at the structure of a ledger that records the interactions between the parties as ledger changes. The definitions presented here address the first question: “What do changes and ledgers look like?”. The basic building blocks of the recorded interactions are actions, which get grouped into transactions, updates, commits, and the Ledger.Running workflow example
Most of the examples in this section look at the following Daml Script scenarios based on the templates from the running example. Two banks first each issue one asset to either Alice or Bob and then Alice proposes a DvP to Bob. Bob accepts the proposal and settles the DvP.AcceptAndSettle choice.
Accept followed by Settle:
Actions
Hierarchical structure
One of the main features of the Ledger Model is a hierarchical action structure. This structure is illustrated using Bob settling the DvP by exercising theSettle choice in the above scenario. Alice and Bob have allocated their assets (contracts #1 and #2) on the ledger to a SimpleDvp contract (#4). These contracts appears as inputs (dashed boxes on the left) in the diagram below.
Settle choice yields an Exercise action, which is the tree of nodes shown in blue. The input contracts on the left are not part of the action. The root node describes the parameters of the choice and references the SimpleDvp input contract #4. It has two subtrees, which perform the asset transfers automatically as part of the Settle choice.
- The left subtree represents Alice exercising the
Transferchoice on herSimpleAssetcontract #1. It consists of two nodes: The root node describes the parameters of the choice and the input contract #1. The child node, which is a one-node subtree of its own, encodes the creation of Bob’s newSimpleAssetcontract #5. - The right subtree is analogous: The root node of the subtree describes Bob exercising the
Transferchoice on hisSimpleAssetcontract #2, and its child encodes the creation of Alice’s newSimpleAssetcontract #6.
Transfer choice on their SimpleAsset input contracts #1 and #2, respectively. And each of the two subtrees contains another subtree, namely the creation of Bob’s and Alice’s new SimpleAsset contracts #5 and #6. Each of these subtrees is an action in its own right. This hierarchical structure induces a subaction relationship explained below and forms the basis for the privacy model.
Definition
Overall, the settlement in the above example contains two types of actions:- Creating contracts
- Exercising choices on contracts.
-
A Create node records the creation of the contract. It contains the following pieces of information:
- The contract ID is a unique identifier of the contract. It is equivalent to the transaction output (TxO) in ledgers based on unspent transaction outputs (UTxO).
- The template ID identifies the Daml code associated with the contract, and its arguments define the contract instance, which is the immutable data associated with the contract ID.
- The signatories are the non-empty set of parties that must authorize the creation and archival of the contract.
- The contract observers, or just observers for short, are the set of parties that will be informed about the contract creation and archival, in addition to the signatories.
signatoryandobserverclauses defined by the template. Create nodes are depicted as shown below. Diagrams often omit fields with empty values and observers that are also signatories. -
An Exercise node records the parameters of a choice that one or more parties have exercised on a contract. It contains the following pieces of information:
- An exercise kind, which is either consuming or non-consuming. Once consumed, a contract cannot be used again; for example, Alice must not be able to transfer her asset twice, as this would be double spending. In contrast, contracts exercised in a non-consuming fashion can be reused, for example for expressing a delegation from one party to another.
- The contract ID on which the choice is exercised. This contract is called the input contract.
- The interface ID if this choice was exercised through a Daml interface.
- The template ID that defines the smart contract code for the choice with the given choice name; and the choice arguments that are passed to the smart contract code.
- An associated set of parties called actors. These are the parties who perform the action. They are specified in the
controllerclause in the Daml template. - An associated set of choice observers. These parties will be informed about the choice being exercised.
- The exercise result as the Daml value returned by evaluating the choice body.
-
A Fetch node on a contract, which demonstrates that the contract exists and is active at the time of fetching. A Fetch behaves like a non-consuming Exercise with no consequences, and can be repeated. The fetch node contains the following pieces of information, analogous to Exercise nodes: contract ID, interface ID, template ID, and the actors, namely the parties who fetch the contract.
Fetch nodes are depicted as shown below.
- A Create action has a Create node as the root. The consequences are empty.
- An Exercise action has an Exercise node as the root and the consequences are the subactions. The Exercise action is the parent action of its consequences.
- A Fetch action as a Fetch node as the root. The consequences are empty.
Examples
An example of a Fetch action appears in theAccept choice on a DvP proposal contract from the template ProposeSimpleDvP. The choice body fetches the SimpleAsset that Bob allocates to the DvP, which checks that the asset contract is active and brings the contract instance into the computation, so that the choice implementation can assert that this asset meets the expectation expressed in the proposal contract. The next diagram shows this Exercise action with the Fetch action as its first consequence.
AcceptAndSettle choice on the ProposeSimpleDvP contract: This choice is non-consuming so that the Accept choice exercised in the choice body can consume the proposal contract. As the next diagram shows, non-consuming Exercises yield multiple references to the same input contract #3. The diagram also shows that fetches have the same effect: input contract #2 is used twice.
Subactions
This example again highlights the hierarchical structure of actions: TheAcceptAndSettle action contains the corresponding actions for Accept and Settle as its consequences.
More generally, for an action act, its proper subactions are all actions in the consequences of act, together with all of their proper subactions. Additionally, act is a (non-proper) subaction of itself.
The subaction relation is visualized below for Bob’s Settle Exercise. Each borderless box contains an action (via its tree of nodes) and the nesting of these boxes encodes the subaction relation. In detail, both the blue and purple boxes are proper subactions of Bob’s Settle action shown in grey. The green box is a proper subaction of the blue and the grey boxes, and the yellow box is a proper subaction of the purple and the grey boxes.
Transactions
A transaction is a list of actions that are executed atomically. Those actions are called the root actions of the transaction. That is, for a transactiontx = act``1``, …, act``n, every act``i is a root action. For example, if Alice and Charlie have made one DvP proposal each for Bob, then Bob may want to both accept simulataneously. To that end, Bob exercises both Accept choices in a single transaction with two root actions (blue and purple), as shown next. Visually, transactions are delimited by the dashed lines on both sides, to distinguish them from actions. Like for actions, the input contracts on the left are not part of the transaction.
Settle action on Alice’s and Bob’s SimpleDvP, the consequences of the Settle action form the following transaction, where actions are ordered left-to-right as before. The transaction consists of two root actions (blue and purple), namely the two Transfer actions of the two legs of the DvP.
Settle action, the next diagram shows all seven proper non-empty subtransactions, each with their dashed delimiters.
Inputs and outputs
The Ledger Model falls into the category of (extended) UTxO-style ledgers where the set of unspent transaction outputs (UTxOs) constitutes the current state of a ledger. Here, the transaction outputs are the contract IDs of the contracts created in a transaction. When a contract is consumed, its contract ID is spent and thus removed from the UTxO set. The data associated with each UTxO is immutable; modifications happen by consuming a contract ID and recreating a new contract with a different contract ID. This Ledger Model extends the UTxO model in two aspects:- A transaction may use a contract without consuming it, for example by exercising a non-consuming choice or fetching it. In such a case, the contract ID remains in the set of UTxOs even though it appears as an input to a transaction.
- Transactions are structured hierarchically and contract IDs created in the transaction may be consumed within the same transaction. For example, inside the
AcceptAndSettleaction, the createdSimpleDvPin the first consequence is consumed by the second consequence. Such contracts are called transient.
Ledger
The transaction structure records the contents of a party interaction. The ledger records two more aspects of an interaction:- An identifier to uniquely refer a particular party interaction.
- The parties who requested a particular party interaction.
TX i for some number i, similar to the transaction view in Daml Studio. On the Ledger API, update IDs are arbitrary strings whose lexicographic order is independent from their order on the ledger.
A commit adds the information who requested a party interaction. It consists of an update and the one or more parties that requested it. Those parties are called the requesters of the commit. In Daml Script, the requesters correspond to the actAs parties given to the submit commands.
Definition: LedgerA Ledger is a directed acyclic graph (DAG) of commits, where the update IDs are unique.
Definition: top-level actionFor a commit, the root actions of its transaction are called the top-level actions. A top-level action of any ledger commit is also a top-level action of the ledger.
c``1 happens before c``2 if and only if the ledger contains a non-empty path from c``1 to c``2, or equivalently, the transitive closure of the graph contains an edge from c``1 to c``2.
The integrity conditions on a ledger require that the happens-before order respects the lifecycle of contracts. For example, the commit that creates a contract must happen before the commit that spends the contract unless they are the same. For the next few sections, we will consider only ledgers that meet these conditions.
- In the first commit, Bank 1 requests the creation of the
SimpleAssetof1 EURissued to Alice (contract #1). - In the second commit, Bank 2 requests the creation of the
SimpleAssetof1 USDissued to Bob (contract #2). - In the third commit, Alice requests the creation of the
SimpleDvpPoposal(contract #3). - In the fourth commit, Bob requests to exercise the
AcceptAndSettlechoice on the DvP proposal.
The integrity constraints do not impose an order between independent commits. In this example, there need not be edges among the first three commits
TX 0, TX 1, and TX 2, so they could be presented in any order.As the Ledger is a DAG, one can always extend the order into a linear sequence via a topological sort. For the next sections, we pretend that the Ledger is totally ordered (unless otherwise specified). We discuss the more general partial orders in the causality section.Integrity
The section on the ledger structure section answered the question “What does the Ledger looks like?” by introducing a hierarchical format to record the party interactions as changes to the Ledger. The section on privacy answered the question “Who sees which changes and data?” by introducing projections. This section addresses the question “Who can request which changes?” by defining which ledgers are valid.Overview
At the core is the concept of a valid ledger: a change is permissible if adding the corresponding commit to the ledger results in a valid ledger. Valid ledgers are those that fulfill three conditions, which are introduced formally below:- Consistency: A consistent Ledger does not allow exercises and fetches on inactive contracts; that is, they cannot act on contracts that have not yet been created or that have already been consumed by an exercise.
- Conformance: A conformant Ledger contains only actions that are allowed by the smart contract logic of the created or used contract. In Daml, templates define this smart contract logic.
- Authorization: In a well-authorized Ledger, the requesters of a change encompass the required authorizers as defined via the controllers and signatories.
Consistency violation example
In this example, Alice tries to transfer her asset twice (“double spend”): once to Bob and once to Charlie, as shown in the following Daml script excerpt. This script is expected to fail at runtime, because it violates consistency.TX 1 and one in TX 2.
Conformance violation example
In the example below, the last transactionTX 4 omits one leg of the DvP workflow:
Bob exercises the Settle choice, but it has only one subaction, namely Alice transferring her IOU.
This violates conformance because the Settle choice body of a SimpleDvP specifies via the two exercise calls that there are always two consequences.
(This situation cannot be expressed as a Daml script scenario
because Daml script ensures that all generated transactions conform to the Daml code.)
Authorization violation examples
Next, we give three examples that show different kinds of authorization violations.Unauthorized transfer
First, Alice attempts to steal Bob’s asset by requesting a transfer in his name. This results in an authorization failure because forTX 1 the actor of the exercise root action differs from the requester.
Skip the propose-accept workflow
Next, Bob wants to skip the propose-accept workflow for creating theSimpleDvP contract and instead creates it out of nowhere and immediately settles it.
This must be treated as an authorization failure, as Alice did not consent to swapping her EUR asset against Bob’s USD asset.
TX 2 is not properly authorized
because Alice is a signatory of the contract #3 created in the first root action even though she did not request the update.
Allocate someone else’s asset
The final example shows that authorization failures may not only happen at root actions. Here, Alice allocates Carol’s CHF asset in the DvP proposal. When Bob tries to settle the DvP, the Exercise to transfer Carol’s asset in the first leg is not properly authorized because Carol did not agree to have her asset transferred away.Transfer choice on her asset.
Interaction with projection
Apart from introducing the validity notion, this page also discusses how validity interacts with privacy, which is defined via projection. To that end, the sections on the different validity conditions analyse the prerequisites under what the following two properties hold:- Preservation: If the Ledger adheres to a condition, then so do the projections. This property ensures that a valid Ledger does not appear as invalid to individual parties, just because they are not privy to all actions on the Ledger.
- Reflection: If the projections adhere to a condition, then so does the Ledger from which these projections were obtained. This property ensures that the condition can be implemented by the distributed Canton protocol where nobody sees the Ledger as a whole.
Consistency
Consistency can be summarized in one sentence: Contracts must be created before they are used, and they cannot be used after they are consumed. This section introduces the notions that are needed to make this precise:- The execution order defines the notions of “before” and “after”.
- Internal consistency ensures that all the operations on a contract happen in the expected order of creation, usage, archival, but does not require that all contracts are created; they may be merely referenced as inputs.
- (Contract) Consistency strengthens internal consistency in that all used contracts must also have been created.
Execution order
The meaning of “before” and “after” is given by establishing an execution order on the nodes of a ledger. The ledger’s graph structure already defines a happens-before order on ledger commits. The execution order extends this happens-before order to all the nodes within the commits’ transactions so that “before” and “after” are also defined for the nodes of a single transaction. This is necessary because a contract can be created and used multiple times within a transaction. In theAcceptAndSettle action of the DvP example, for example,
contract #3 is used twice (once in the non-consuming exercise at the root and once consumingly in the first consequence)
and contract #4 is created and consumed in the same action.
Definiton: execution order
For two distinct nodes n₁ and n₂ within the same action or transaction, n₁ executes before n₂
if n₁ appears before n₂ in the preorder traversal of the (trans)action, noting that the transaction is an ordered forest.
For a ledger, every node in commit c₁ executes before every node in commit c₂
if the commit c₁ happens before c₂.
Diagrammatically, the execution order is given by traversing the trees from root to leaf and left to right:
the node of a parent action executes before the nodes in the subactions, and otherwise the nodes on the left precede the nodes on the right.
For example, the following diagram shows the execution order with bold green arrows for the running DvP example.
So a node n₁ executes before n₂ if and only if there is a non-empty path of green arrows from n₁ to n₂.
The diagram grays out the parent-child arrows for clarity.
Internal consistency
Internal consistency ensures that if several nodes act on a contract within an action, transaction, or ledger, then those nodes execute in an appropriate order, namely creation, usage, archival. Internal contract consistency does not require Create nodes for all contracts that are used. This way, internal contract consistency is meaningful for pieces of a ledger such as individual transactions or actions, which may use as inputs the contracts created outside of the piece. Definition: internal consistency An action, transaction, or ledger is internally consistent for a contractc
if for any two distinct nodes n₁ and n₂ on c in the action, transaction, or ledger,
all of the following hold:
- If n₁ is a Create node, n₁ executes before n₂.
- If n₂ is a consuming Exercise node, then n₁ executes before n₂.
Internal consistency constrains the order of the commits in a Ledger via the execution order.
In the running DvP example,
TX 0, TX 1, and TX 2 all create contracts that TX 3 uses.
Internal consistency therefore demands that these create nodes execute before the usage nodes in TX 3.
So by the definition of the execution order, TX 0, TX 1, and TX 2 all must happen before TX 3
(although internal consistency does not impose any particular order among TX 0, TX 1, and TX 2).Definition
Consistency strengthens internal consistency in that used contracts actually have been created within the action, transaction, or ledger. Definition: consistency An action, transaction, or ledger is consistent for a contract if all of the following hold:- It is internally consistent for the contract.
- If a node uses the contract, then there is also a node that creates the contract.
TX 0 and thus contains only commits TX 1 to TX 3, it is still internally consistent, but not consistent,
because TX 3 uses the contract #1, but there is no create node for #1 in TX 1 to TX 3.
Consistency and projection
This section looks at the conditions under which projections preserve and reflect (internal) consistency.Projections preserve consistency for stakeholders
For preservation, projections retain the execution order and preserve internal consistency. Yet, consistency itself is preserved in general only for contract stakeholders. For example, Alice’s projection of the DvP workflow is not consistent because it lacksTX 1 and therefore the creation of contract #2 used in TX 3.
Fortunately, consistency behaves well under projections if we look only at contracts the parties are stakeholders of.
In detail, if an action, transaction, or ledger is (internally) consistent for a set of contracts C
and P is a set of parties such that every contract in C has at least one stakeholder in P,
then the projection to P is also (internally) consistent for C.
To see this, note that the execution order of the projection of an action or transaction to P
is the restriction of the execution order of the unprojected action or transaction to the projection.
That is, if n₁ and n₂ are two nodes in the projection,
then n₁ executes before n₂ in the projection if and only if
n₁ executes before n₂ in the original (trans)action.
Accordingly, projections preserve internal consistency of an action or transaction too.
Moreover, the projection to P never removes a Create node if one of the stakeholders is in P.
Therefore, consistency is preserved too.
For ledgers, the same argument applies with the current simplification of totally ordered ledgers.
The causality section relaxes the ordering requirement, but makes sure
that projections continue to preserve (internal) consistency for the parties’ contracts.
Signatories check consistency on projections
From Canton’s perspective, the reflection property is at least as important: If the projection of a (trans)action or ledger to a set of partiesP is (internally) consistent for a set of contracts C
where each contract has at least one signatory in P,
then so is the (trans)action or ledger itself.
This statement can be shown with a similar argument.
Importantly, reflection requires a signatory of the contracts in P, not just a stakeholder.
The following example shows that the propery does not hold if P contains a stakeholder, but no signatory.
To that end, we extend the SimpleAsset template with a non-consuming Present choice
so that the issuer and owner can show the asset to a choice observer viewer:
Present command,
and the Synchronizer happens to order Alice’s submission first.
Conformance
The conformance condition constrains the actions that may occur on the ledger. The definitions in this section assume a given contract model (or a model for short) that specifies the set of all possible actions. In practice, Daml templates define such a model as follows:- Choices declare the controller and the choice observers and constrain via their body the valid values in the exercised contract and choice arguments. Their body defines the subactions (by creating, fetching or exercising contracts) and the Exercise result.
-
The
ensureclause on the template constrains the valid arguments of a Create node.
SimpleDvP.Settle exercises Transfer on two contracts and therefore requires that there are two subactions.
The action on the ledger however has only one of the two subactions and therefore violates conformance.
This example demonstrates why the contract model specifies actions instead of nodes:
a set of acceptable nodes cannot catch when a consequence is missing from an action,
because nodes ignore the tree structure.
Conformance and projection
Like consistency, conformance to a Daml model behaves well under projections. If an action, transaction or ledger conforms to a Daml model, then all their projections also conform to the same Daml model. In fact, Daml models enjoy the stronger property that every subaction of a Daml-conformant action conforms itself. This essentially follows from two observations:- The controllers of any choice may jointly exercise it on any contract, and the signatories of a contract may jointly create the contract, without going through some predefined workflow. So contract creations and choices are essentially public.
- The Daml language is referentially transparent. That is, all inputs and outputs of a transaction are explicitly captured in contracts, choice arguments and exercise results.
AcceptAndSettle choice for Bank 2.
Yet, there is no Ledger API command to fetch a contract, as there are only commands for creating and exercising contracts.
Second, the Ledger API command language does not support feeding the result of an Exercise as an argument to a subsequent command.
For example, suppose that the AcceptAndSettle choice of ProposeSimpleDvP was actually implemented on a helper template AcceptAndSettleDvP as shown below.
Execute choice.
TX 3 consists of two root actions, where the second exercises a choice on a contract created in a consequence of the first.
Authorization
The last validity condition ensures that only the indended parties can request a change, and thereby rules out the authorization violation examples. Authorization requirements are expressed in Daml using the signatories and observers of a contract and the controllers of choices. This section introduces the notions to formalize this:- Required authorizers define the set of parties who must have consented to an action.
- The authorization context captures the parties who have actually authorized an action.
- Well-authorization demands that the authorization context includes all the required authorizers.
Required authorizers
Every node defines a non-empty set of parties who must have consented to the action of this node. This set is called the required authorizers of the node and defined as follows: For Create nodes, the required authorizers are the signatories of the contract, and for Exercise and Fetch nodes, the required authorizers are the actors of the node. For the running example where Bob skips the propose-accept workflow, the following table lists for each party the nodes for which they are a required authorizer. For example, node ③ has the required authorizers Alice and Bob because they are the signatories of contract #3. Required authorizers in the example where Bob tries to skip the propose-accept workflow| Node | Bank1 | Bank2 | Alice | Bob |
|---|---|---|---|---|
| ① | signatory | |||
| ② | signatory | |||
| ③ | signatory | signatory | ||
| ④ | actor | |||
| ⑤ | actor | |||
| ⑥ | signatory | |||
| ⑦ | actor | |||
| ⑧ | signatory |
Authorization context
In a Canton ledger, a party can authorize a subaction of a commit in two ways:- The requesters of a commit authorize every top-level action of the commit.
- For an Exercise action, the signatories of the input contract and the actors of the action jointly authorize every consequence of the action.
- Bank1 because Bank1 is the signatory of the input contract of the parent node ⑤.
- Alice because Alice is the actor on the parent node ⑤.
| Node | Bank1 | Bank2 | Alice | Bob |
|---|---|---|---|---|
| ① | requester of TX 0 | |||
| ② | requester of TX 1 | |||
| ③ | requester of TX 2 | |||
| ④ | requester of TX 2 | |||
| ⑤ | signatory on #3 | signatory on #3 + actor of ④ | ||
| ⑥ | signatory on #1 | actor of ⑤ | ||
| ⑦ | signatory on #3 | signatory on #3 + actor of ④ | ||
| ⑧ | signatory on #2 | actor of ⑦ |
Well-authorization
Well-authorization ensures that the authorizing parties and the required authorizers fit together. Definition: Well-authorization An action is internally well-authorized if for every proper subaction, the authorization context contains all the required authorizers of the subaction. An action is well-authorized if it is internally well-authorized and the authorization context of the action contains all the required authorizers of the action. A commit is well-authorized if every root action is well-authorized. In the running example, well-authorization requires that every non-empty cell in the required authorizers table is also non-empty in the authorization context table. For example, the commitTX 0 is well-authorized because it contains only one subaction ①
and the required authorizer Bank1 is also the requester of the commit.
Conversely, the commit TX 2 is not well-authorized because ③’s required authorizers include Alice who is not in ③’s authorization context.
This authorization failure captures the problem with this commit TX 2:
The Ledger does not contain any record of Alice consenting to the DvP.
In contrast, the Exercise action at ④ is well-authorized.
This illustrates how authorization flows from the signatories of a contract to the consequences of the choices.
Assuming that the signatories Alice and Bob entered the SimpleDvP contract #3,
the authorization rules allow Bob, the one controller of the Settle choice, to swap the two assets
even though Bob does not own one of the assets (#1).
In other words, Alice delegates via the SimpleDvp contract #3 to Bob the right to transfer her asset #1.
A similar flow of authorization also happens in the propose-accept workflow for the SimpleDvP contract in the correct workflow:
In TX 2, Alice proposes the ProposeSimpleDvP contract #3 as a signatory.
When Bob accepts the proposal with the Accept choice,
Alice’s authority flows to the creation of the SimpleDvP contract #4,
where both Alice and Bob are signatories.
Well-authorization with projection
The example of the wrongly allocated asset illustrates the difference between well-authorization and internal well-authorization. The action rooted at node ⑨ is internally well-authorized because it has only one proper subaction with node ⑩ whose authorization context includes the required authorizer Bank1. Yet, the action itself is not well-authorized because the required authorizers of ⑨ include Carol, but its authorization context contains only Alice and Bob, as they are signatories of the input contract #4 of node ⑧. The authorization failure disappears in the projection to Bank1 though, because the projection of a ledger forgets the requesters of the commits. So from Bank1’s perspective, the asset transfer looks fine.Authorization vs. conformance
Well-authorization and conformance are both necessary to ensure that the Ledger contains only the intended changes. To illustrate this, we modify the example of the wrongly allocated asset such that node ⑨ specifies Alice as the actor instead of Carol. Then, the action (and the ledger as a whole) is well-authorized. Yet, it no longer conforms to the Daml model, because theTransfer choice defines the controller to be the owner of the asset #1, which is Carol in this case.
This conformance failure does show up in Bank 1’s projection, unlike corresponding the well-authorization failure from the previous section.
Validity
Having formalized the three conditions consistency, conformance and well-authorization, we can now formally define validity. Definition: Valid Ledger A Canton Ledger is valid for a set of partiesP if all of the following hold:
-
The Ledger is consistent for contracts whose signatories include one of the parties in
P. - The Ledger conforms to the Daml templates.
-
Every root action on the Ledger is internally well-authorized and its required authorizers in
Pare requesters of the commit.
P comes from privacy.
As discussed above, consistency and well-authorization are not common knowledge.
The Canton protocol therefore relies on the relevant parties to check these conditions.
Accordingly, the protocol only ensures these properties for the parties that follow the protocol.
Virtual Global Ledger
The Canton protocol creates a Virtual Global Ledger (VGL) that is valid for the honest parties and such that each of these parties sees their projection of VGL. Honesty here means that the parties and the nodes they are using correctly follow the Canton protocol subject to the Byzantine fault tolerance configured in the topology. This Virtual Global Ledger is not materialized anywhere due to privacy: in general, no node knows the entirety of the ledger. In the DvP ledger, for example, if the Banks, Alice, and Bob are hosted on different systems, only the projections to the Banks, to Alice, and to Bob materialize on these systems, but none of them sees the unprojected Ledger as a whole. Accordingly, the Canton protocol cannot ensure the validity of the Virtual Global Ledger as a whole. For example, if a group of signatories decides to commit a double spend of a contract, then this is their decision. Since each spend may be witnessed by a different honest party, the VGL contains both spends and is therefore inconsistent for this contract.Interaction with projection
Preservation and reflection for validity is difficult to formalize because projections discard the requesters of a commit. Therefore, we analyze these two properties for a weak validity notion, namely validity without the constraint on the requesters of the commit. Then, projection preserves weak validity in the following sense: If a Ledger is weakly valid for a set of partiesP, then its projection to a set of parties Q is weakly valid for the parties in both P and Q.
The restriction of the parties to the intersection of P and Q takes care of the problem of the projected-away contract creations discussed in the consistency section.
Reflection does not hold for weak validity in general when we look only at projections to sets of honest parties.
For example, consider a Ledger with a root action that no honest party is allowed to see.
So none of the projections contains this root action and therefore the projections cannot talk about its conformance or internal well-authorization.
Fortunately, this is not necessary either, because we care only about the pieces of the Ledger that are visible to some honest party.
More formally, two Ledgers are said to be equivalent for a set of parties Q if the projections of the two Ledgers to Q are the same.
Then reflection holds in the sense that there is an equivalent weakly valid Ledger.
Let F be a set of sets of parties whose union contains the set of parties Q.
If for every set P in F, the projection of a Ledger L to P is weakly valid for P insterected with Q,
then the projection of L to Q is weakly valid.
Note that this projection of L to Q is equivalent to L for Q due to the absorbtion property of projection.
Privacy
The ledger structure section answered the question “What does the Ledger looks like?” by introducing a hierarchical format to record the party interactions as changes. This section addresses the question “Who sees which changes and data?”. That is, it explains the privacy model for Canton Ledgers. The privacy model of Canton Ledgers is based on a need-to-know basis, and provides privacy on the level of subtransactions. Namely, a party learns only those parts of party interactions that affect contracts in which the party has a stake, and the consequences of those interactions. The hierarchical structure is key here because it yields a natural notion of sub-transaction privacy. To make the sub-transaction privacy notion precise, we introduce the concepts of informee and witness.Informee
A party can take different roles in Daml templates and choices; the party can be declared assignatory, choice controller, or contract or choice observer. For a contract, a party is a stakeholder if it is a signatory or contract observer of the contract.
- Every contract and choice
observershould observe changes to the contract (creation or archival) and exercises of a choice, respectively, as the name suggests. - A
signatoryis bound by a contract and thus has a stake in it; they should learn when the contract is created or used. - An actor of an Exercise, which is the
controllerof the choice, has a stake in the action and should therefore see the exercise; they may not have a stake in the contract though.
| Action | Signatories | Contract observers | Actors | Choice observers |
|---|---|---|---|---|
| Create | X | X | ||
| consuming Exercise | X | X | X | X |
| non-consuming Exercise | X | X | X | |
| Fetch | X | X |
Templates can declare
preconsuming and postconsuming choices. Daml compiles such choices to a non-consuming choice whose first or last consequence exercises the Archive choice on the template. Accordingly, contract observers are only informees of the Archive subaction, but not of the main Exercise action itself.AcceptAndSettle action have the informees shown in the blue hexagons of the next figure. For example, Alice is an informee of the root node ① because she is a signatory of the input contract #3, and Bob is an informee because he is the actor of the choice. Similarly, Bank 2 and Bob are informees of the Fetch node ③ because Bank 2 is a signatory of the input contract #2 and Bob is the actor. Had Bob not been the actor, he would not be an informee because contract observers are not automatically informees of non-consuming Exercises and Fetches.
Witness
A single node can be part of multiple actions. For example, the diagram below extends the subaction diagram with the informees shown in the top right corner of the borderless box for each subaction. Here, the Create node ③ is part of three subactions, namely those rooted at nodes ①, ②, and ③. Accordingly, this Create node is shown to the informees of all these actions, even if they are not informees of the node itself. Those parties are called witnesses. Formally, for a given transactiontx, the witnesses of a node in tx are the union of the informees of all subactions of tx that contain the node. In particular, every informee of the node is also a witness.
The diagram shows the witnesses of a subaction in purple on its root action. For node ③, the witnesses are Alice, Bob, and Bank 1, because Bob is an informee of ① and ③; Bank 1 is an informee of ② and ③; and Alice is an informee of ① and ②.
Projection
Informees should see the changes they are entitled to see, but this does not mean that they are entitled to see the entirety of any transaction that includes such a change. This is made precise through projections of a transaction, which define the view that a group of parties gets on a transaction. Intuitively, given a transaction within a commit, a group of parties sees only the subtransaction consisting of all actions on contracts whose informees include at least one of the parties. Equivalently, the group of parties sees only those nodes whose witnesses include at least one of the parties. Thus, privacy is obtained on the subtransaction level. This section first defines projections for transactions and then for ledgers.Transaction projection
The next diagram gives an example for a transaction with theAcceptAndSettle Exercise action as the only root action, whose informees are shown in the diagrams above.
AcceptAndSettle choice on Alice’s ProposeSimpleDvP contract, the projection to either Alice or Bob or both consists of the whole Exercise action. As an action consists of the whole subtree underneath its root node, Alice and Bob each see all the nodes they are witnesses of. For example, Alice’s projection includes the Fetch subaction, Bob’s Transfer exercise of on #2, and the creation of Bob’s SimpleAsset contract #5. Similarly, Bob’s projection includes Alice’s Transfer Exercise on #1 and the creation of Alice’s SimpleAsset contract #6.
In contrast, the banks are not informees of the root action. In fact, Bank 1 appears as an informee only in the Transfer Exercise action on #1 and its subaction, the creation of Bob’s new asset #5. Accordingly, the projection to Bank 1 consists of just this Exercise action. Bank 2 appears as an informee of two unrelated actions in the tree: the Fetch action and the Transfer Exercise action on #2. The projection to Bank 2 therefore consists of a transaction with these two actions as root actions. This shows that projection can turn a single root action into a list of subactions.
Note the privacy implications of the banks’ projections. While each bank learns that a
Transfer has occurred from Alice to Bob or vice versa, each bank does not learn anything about why the transfer occurred. In particular, Bank 2 does not learn what happens between the Fetch and the Exercise on contract #2. In practice, this means that Bank 1 and Bank 2 do not learn what Alice and Bob is exchanging their asset for, providing privacy to Alice and Bob with respect to the banks.Definition: projectionThe projection of a transaction for a set
P of parties is the subtransaction obtained by doing the following for each root action act of the transaciton.- If
Pcontains at least one of the informees ofact, keepactas-is, including its consequences. - Else, if
acthas consequences, replaceactby the projection (forP) of its consequences, which might be empty. - Else, drop
actincluding its consequences.
P contains a node if and only if P contains at least one of the witnesses of the node.
As a projection is a transaction, it is possible to project a projection further. The projection operation has the following absorbtion property: Projection to decreasing subsets of parties is absorbing. That is, if a set of parties P is a subset of Q, then projecting a transaction first to Q and then to P is the same as projecting it directly to P. Intuitively, this property expresses the fact that a group of parties jointly learns at least as much about a transaction as any subgroup of these parties learns by themselves. The converse is false, as the above example with projection to Banks 1 and 2 has shown.
Conversely, if P is not a subset of Q, then projecting a transaction first to Q and then to P will merely result in a subtransaction of the projection to P. For example, if we project the above projection for Bank 1 to Bob, the resulting transaction consists only of the Create action for contract #5. This is a proper subtransaction of Bob’s projection.
This difference reflects that Bank 1 learns less about the Exercise node than Bob. In particular, Bank 1 cannot infer from its projection that Bob is a witness of the Exercise node. This is a general pattern: the informees of an action may not learn about witnesses of nodes therein. This is crucial from a privacy perspective as it hides who is involved in the hidden parts of the transaction.
Ledger projection
Finally, the projection of a ledgerl for a set P of parties is a DAG of updates obtained as follows:
- Project the transaction of each update in
lforP, but retain the update ID. - Remove updates with empty transactions from the result.
Transfer choice on contract #1.
Projecting the ledger of the complete DvP example yields the following projections for each party.
- Alice sees all of the first, thrid, and forth commit as she is an informee of all root actions. In contrast, Alice does not see anything of the second commit, as she is not a stakeholder of Bob’s
SimpleAssetof 1 USD. This transaction is not present in Alice’s projection at all. Yet, the output of this transaction (contract #2) is used in the last commit of Alice’s projection. Accordingly, contract #2 is shown as an input to the left, outside of the ledger. This effect is discussed below under retroactive divulgence. - Bob’s projection is analogous to Alice’s: He sees everything of the second, third, and forth commit, but nothing of the first commit and instead merely contract #1 as an input.
- Banks 1 and 2 only see the commits in which they create their
SimpleAssetand theTransferExercises on them. Additionally, Bank 2 sees the Fetch of theSimpleAssetin the last commit, as already discussed above for transaction projections.
TX 3. They can therefore infer that their projections have happened in the same atomic transaction even though their projections do not share a single node.
A user of a Participant Node can request the Ledger projection for the user’s parties via the updates tree stream.
Divulgence: When non-stakeholders see contracts
The guiding principle for the privacy model of Canton ledgers is that contracts should only be shown to their stakeholders. However, ledger projections can cause contracts to become visible to other parties as well. Showing contracts to non-stakeholders through ledger projections is called divulgence. Divulgence is a deliberate choice in the design of Canton Ledgers and comes in two forms:-
Immediate divulgence refers to witnesses seeing contract creations they are not an informee of. In the example of ledger projections of the DvP, Bob is a witness of the Create action for Alice’s new
SimpleAsset(contract #6), but not an informee. Conceptually, at the instant where Bob exercises theTransferchoice, he also gains a temporary stake in the outcome of theTransfer, namely to see that the asset now belongs to Alice. In general, there is no point in hiding the consequences of an action. Bob could anyway compute the consequences of the actions it is an informee of, because Daml is deterministic. -
Retroactive divulgence refers to an input contract being shown to the non-informee witnesses of a node using this contract. For example, the Fetch on Bob’s
SimpleAsset(contract #2) is visible to Alice and Alice’s projection therefore references this contract as an input even though the Create action for #2 is not part of Alice’s projection. Retroactive divulgence enables Alice to validate the transactions in her projection (seeda-model-consistencyfor ledger integrity). That is, Alice can check that Bob does allocate a suitableSimpleAssetaccording to what she specified in her proposal. Retroactive divulgence does not make Alice a witness of the Create action for Bob’sSimpleAsset(contract #2), because an input contract is not the same as its Create action. In the diagrams, this distinction is visualized via the dashed border for input contracts and them being placed to the left.
Disclosure: When non-stakeholders use contracts
Divulgence from the previous section refers to parties learning about contracts they are not a stakeholder of. Disclosure is about such parties using contracts in their own transactions. Recall from the running example that Bob usessubmit with a disclosure for the exercising Settle choice. This is because Bob (and its Participant Node) in general does not know about the SimpleAsset contract #2 that Alice has allocated to the proposal. Disclosure means that Alice tells Bob via an off-ledger communication channel about this contract. In the Daml script running example, the script itself is the communication channel. In real-world contexts, Alice would offer an API for Bob to retrieve the relevant data.
It is a design decision that immediate divulgence does not entail disclosure for subsequent transactions. For example, after the DvP has been settled, Alice creates another DvP proposal for Bob to swap the two assets again:
SimpleAsset even though Bob is a witness of the creation of Alice’s SimpleAsset. A plain submit without disclosure does not work.
The motivation for not using immediate divulgence implicitly for disclosure is that it leads to brittle workflows. The problem is that the non-stakeholders only learn about the creation of the contract, but not about subsequent actions on the contract like archivals. Accordingly, there is no general rule as to how long the non-stakeholder should long to keep the contract around. Keeping it for too long will waste storage; and keeping it too short may break certain applications. Instead, this rule forces the application to explicitly design for disclosure even for divulged contracts and come up with a suitable application-specific rule.
An alternative approach to disclosure is to replace the original SimpleAsset contract by one on which the Bob becomes a contract observer. This requires extending the contract model with a (consuming) exercise action on the SimpleAsset that creates a new SimpleAsset, with observers of Alice’s choice. In addition to the increase in actions on the Ledger, the two approaches differ in in who learns about the parties that are informed about the contract:
- If Alice discloses her
SimpleAssetto Bob via an off-ledger channel, only Alice and Bob need to know about this disclosure. So when Alice discloses the same contract to Charlie, Charlie does not need to know that Alice had already shown the contract to Bob, and Bob does not need to know that Alice is disclosing it to Charlie. - In contrast, when Alice adds Bob as a contract observer and then subsequently adds Charlie as another observer, Bob as a contract observer is notified about the archival and the creation. Similarly, Charlie learns that Bob is an observer on the contract, too. That is, all stakeholders learn about each other. This created a privacy problem when Alice actually does not want that Bob and Charlie know of each other.
N observers appears in the projection of at least those N parties. So the size of all projections together is already quadratic in N as an action of size at least N appears in N different projection. If the observers are added one by one, then N archives and creations are needed, which means the size of all projections together is cubic in N.
Shape-revealing projection
As explained above, projections define the pieces of the ledger that a set of parties can see, and thereby also the pieces that they can not see. For example, the above transaction projection for Bank 2 omits what happens between the Fetch and the Exercise on contract #2 and thereby implies that Bank 2 has no way of finding this out on their own. In practice, this strong privacy statement assumes that Bank 2 interacts with the Ledger only via the Ledger API of their Participant Nodes. In contrast, if Bank 2 observes the communication patterns between the Participant Nodes, Bank 2 might be able to deduce that Bank 1 was also involved in this transaction. Similarly, if Bank 2 can inspect the on-wire data of such communication, as is for example possible to some extent on the Global Synchronizer, then Bank 2 can infer some information about the shape of the original transaction and the parties involved, beyond what is visible in the projection. This is because the synchronizer needs this shape information for its two-phase commit protocol. This section defines the shape that overapproximate the information that can leak via messages exchanged via the synchronizer. Overapproximation here means that a curious party may not be able to fully reconstruct the shape of a transaction on the ledger, for example due to optimizations in the synchronization protocol. The synchronization protocol uses a notion of the required confirmers for a node, which are a subset of the informees. The required confirmers are therefore part of the shape and defined as follows. Definition: required confirmers The required confirmers for a Create node are the signatories and for an Exercise or Fetch node are the signatories and actors. The shape of a node is defined as follows: Definition: node shape The shape of a node consists of the following pieces of information:- The informees of the node.
- The size of the encoding of the node contents and the input contract, if any.
- The required confirmers for the node.
P of parties is obtained as follows for each root action act of the transaction:
-
If
Pcontains at least one of the informees ofact, keepactas-is, including its consequences. -
Else, replace the node of
actwith its shape and the shape-revealing projection of the consequences ofactbecomes the children of the node shape.
l for a set P of parties is obtained by replacing the transaction in each commit by its shape-revealing projection for P while retaining the update ID and the requesters.
For example, the shape-revealing projection of the above DvP ledger for Bank 2 looks as follows.
Node shapes are shown as empty boxes with a ? inside and annotated with the informees and the required confirmers (underlined).
Importantly, the shape-revealing projection retains the requesters and the empty projected transactions, unlike for normal projections.
Conversely, the node shapes do not show the inputs and outputs.
Thus despite the shape of individual transactions being visible to all parties,
the structure of the overall transaction graph remains private.
Synchronizer-aware projection
- Disentangle abuse of ledger term: the VSL from what is coordinated over a synchronizer
- Define synchronizer-aware projections (assign and unassign events)
- The Ledger API
- The Daml Ledger Model
- Local ledgers and causality graphs
Interoperability for Daml ledgers is under active development. This document describes the vision for interoperability and gives an idea of how the Ledger API services may change and what guarantees are provided. The described services and guarantees may change without notice as the interoperability implementation proceeds.
Interoperability Examples
Topology
Participant Nodes connect to Daml ledgers and parties access projections of these ledgers via the Ledger API. The following picture shows such a setup.- There is a set of interoperable Daml ledgers: Ledger 1 (green) and Ledger 2 (yellow).
- Each Participant Node is connected to a subset of the Daml ledgers.
- Participant Nodes 1 and 3 are connected to Ledger 1 and 2.
- Participant Node 2 is connected to Ledger 1 only.
- Participant Nodes host parties on a subset of the Daml ledgers they are connected to. A Participant Node provides a party access to the Daml ledgers that it hosts the party on.
- Participant Node 1 hosts Alice on Ledger 1 and 2.
- Participant Node 2 hosts Alice on Ledger 1.
- Participant Node 3 hosts the painter on Ledger 1 and 2.
Aggregation at the Participant
The Participant Node assembles the updates from these ledgers and outputs them via the party’s Update Service and State Service. When a Participant Node hosts a party only on a subset of the interoperable Daml ledgers, then the Update and State Services of the Participant Node are derived only from those ledgers. For example, in the above topology, when a transaction creates a contract with stakeholder Alice on Ledger 2, thenP1’s transaction stream for Alice will emit this transaction and report the contract as active, but Alice’s stream at P2 will not.
Enter and Leave Events
With interoperability, a transaction can use a contract whose creation was recorded on a different ledger. In the above topology, e.g., one transaction creates a contractc1 with stakeholder Alice on Ledger 1 and another archives the contract on Ledger 2. Then the Participant Node P2 outputs the Create action as a CreatedEvent, but not the Exercise in form of an ArchiveEvent on the Update Service because Ledger 2 can not notify P2 as P2 does not host Alice on Ledger 2. Conversely, when one transaction creates a contract c2 with stakeholder Alice on Ledger 2 and another archives the contract on Ledger 1, then P2 outputs the ArchivedEvent, but not the CreatedEvent.
To keep the transaction stream consistent, P2 additionally outputs a Leave c1 action on Alice’s transaction stream. This action signals that the Participant Node no longer outputs events concerning this contract; in particular not when the contract is archived. The contract is accordingly no longer reported in the State Service and cannot be used by command submissions.
Conversely, P2 outputs an Enter c2 action some time before the ArchivedEvent on the transaction stream. This action signals that the Participant Node starts outputting events concerning this contract. The contract is reported in the State Service and can be used by command submission.
The actions Enter and Leave are similar to a Create and a consuming Exercise action, respectively, except that Enter and Leave may occur several times for the same contract whereas there should be at most one Create action and at most one consuming Exercise action for each contract.
These Enter and Leave events are generated by the underlying interoperability protocol. This may happen as part of command submission or for other reasons, e.g., load balancing. It is guaranteed that the Enter action precedes contract usage, subject to the trust assumptions of the underlying ledgers and the interoperability protocol.
A contract may enter and leave the visibility of a Participant Node several times. For example, suppose that the painter submits the following commands and their commits end up on the given ledgers.
- Create a contract
cwith signatories Alice and the painter on Ledger 2 - Exercise a non-consuming choice
ch1oncon Ledger 1. - Exercise a non-consuming choice
ch2oncon Ledger 2. - Exercise a consuming choice
ch3oncon Ledger 1.
P2 provides for A contains five actions involving contract `c`: Enter, non-consuming Exercise, Leave, Enter, consuming Exercise. Importantly, P2 must not omit the Leave action and the subsequent Enter, even though they seem to cancel out. This is because their presence indicates that P2’s event stream for Alice may miss some events in between; in this example, exercising the choice ch2.
The flat transaction stream by P2 omits the non-consuming exercise choices. It nevertheless contains the three actions Enter, Leave, Enter before the consuming Exercise. This is because the Participant Node cannot know at the Leave action that there will be another Enter action coming.
In contrast, P1 need not output the Enter and Leave actions at all in this example because P1 hosts Alice on both ledgers.
Cross-ledger Transactions
With interoperability, a cross-ledger transaction can be committed on several interoperable Daml ledgers simultaneously. Such a cross-ledger transaction avoids some of the synchronization overhead of Enter and Leave actions. When a cross-ledger transaction uses contracts from several Daml ledgers, stakeholders may witness actions on their contracts that are actually not visible on the Participant Node. For example, suppose that the split paint counteroffer workflow from the causality examples is committed as follows: The actions onCounterOffer and PaintAgree contracts are committed on Ledger 1. All actions on Ious are committed on Ledger 2, assuming that some Participant Node hosts the Bank on Ledger 2. The last transaction is a cross-ledger transaction because the archival of the CounterOffer and the creation of the PaintAgreement commits on Ledger 1 simultaneously with the transfer of Alice’s Iou to the painter on Ledger 2.
For the last transaction, Participant Node 1 notifies Alice of the transaction tree, the two archivals and the PaintAgree creation via the Update Service as usual. Participant Node 2 also output’s the whole transaction tree on Alice’s transaction tree stream, which contains the consuming Exercise of Alice’s Iou. However, it has not output the Create of Alice’s Iou because Iou actions commit on Ledger 2, on which Participant Node 2 does not host Alice. So Alice merely witnesses the archival even though she is an informee of the exercise. The Exercise action is therefore marked as merely being witnessed on Participant Node 2’s transaction tree stream.
In general, an action is marked as merely being witnessed when a party is an informee of the action, but the action is not committed on a ledger on which the Participant Node hosts the party. Unlike Enter and Leave, such witnessed actions do not affect causality from the participant’s point of view and therefore provide weaker ordering guarantees. Such witnessed actions show up neither in the flat transaction stream nor in the State Service.
For example, suppose that the Create PaintAgree action commits on Ledger 2 instead of Ledger 1, i.e., only the CounterOffer actions commit on Ledger 1. Then, Participant Node 2 marks the Create PaintAgree action also as merely being witnessed on the transaction tree stream. Accordingly, it does not report the contract as active nor can Alice use the contract in her submissions via Participant Node 2.
Multi-ledger Causality Graphs
This section generalizes causality graphs to the interoperability setting. Every active Daml contract resides on at most one Daml ledger. Any use of a contract must be committed on the Daml ledger where it resides. Initially, when the contract is created, it takes up residence on the Daml ledger on which the Create action is committed. To use contracts residing on different Daml ledgers, cross-ledger transactions are committed on several Daml ledgers. However, cross-ledger transactions incur overheads and if a contract is frequently used on a Daml ledger that is not its residence, the interoperability protocol can migrate the contract to the other Daml ledger. The process of the contract giving up residence on the origin Daml ledger and taking up residence on the target Daml ledger is called a contract transfer. The Enter and Leave events on the transaction stream originate from such contract transfers, as will be explained below. Moreover, contract transfers are synchronization points between the origin and target Daml ledgers and therefore affect the ordering guarantees. We therefore generalize causality graphs for interoperability. Definition »Transfer action« A transfer action on a contractc is written Transfer c. The informees of the transfer actions are the stakeholders of c.
In the following, the term action refers to transaction actions (Create, Exercise, Fetch, and NoSuchKey) as well as transfer actions. In particular, a transfer action on a contract c is an action on c. Transfer actions do not appear in transactions though. So a transaction action cannot have a transfer action as a consequence and transfer actions do not have consequences at all.
Definition »Multi-Ledger causality graph«
A multi-ledger causality graph G for a set Y of Daml ledgers is a finite, transitively closed, directed acyclic graph. The vertices are either transactions or transfer actions. Every action is possibly annotated with an incoming ledger and an outgoing ledger from Y according to the following table:
| Action | incoming ledger | outgoing ledger |
|---|---|---|
| Create | no | yes |
| consuming Exercise | yes | no |
| non-consuming Exercise | yes | yes |
| Fetch | yes | yes |
| NoSuchKey | no | no |
| Transfer | maybe | maybe |
c with signatories Alice and the painter, the four transactions yield the following multi-ledger causality graph. Incoming and outgoing ledgers are encoded as colors (green for Ledger 1 and yellow for Ledger 2). Transfer vertices are shown as circles, where the left half is colored with the incoming ledger and the right half with the outgoing ledger.
As for ordinary causality graphs, the diagrams for multi-ledger causality graphs omit transitive edges for readability.
tx4 is a cross-ledger transaction because its actions have more than one color.
Consistency
Definition »Ledger trace« A ledger trace is a finite list of pairs(a``i``, b``i``) such that b``i - 1 = a``i for all i > 0. Here a``i and b``i identify Daml ledgers or are the special value NONE, which is different from all Daml ledger identifiers.
Definition »Multi-Ledger causal consistency for a contract«
Let G be a multi-ledger causality graph and X be a set of actions from G on a contract in c. The graph G is multi-ledger consistent for the contract c on X if all of the following hold:
- If
Xis not empty, thenXcontains a Create or at least one Enter action. If it contains a create, then this create precedes all other actions inX. If it does not, then there exists one Enter action that precedes all other actions inX. Xcontains at most one Create action.- If
Xcontains a consuming Exercise actionact, thenactfollows all other actions inXinG’s action order. - All Transfer actions in
Xare ordered with all other actions inX. - For every maximal chain in
X(i.e., maximal totally ordered subset ofX), the sequence of(incoming ledger, outgoing ledger)pairs is a ledger trace, usingNONEif the action does not have an incoming or outgoing ledger annotation.
c. In particular, there is only one maximal chain in the actions on c, namely
Createand for each edgec->tf1-> ExeNBcch1->tf2-> ExeNBcch2->tf3-> ExeNBcch3,
act``1 -> act``2, the outgoing ledger color of act``1 is the same as the incoming ledger color of act``2. The restriction to maximal chains ensures that no node is skipped. For example, the (non-maximal) chain
Createis not a ledger trace because the outgoing ledger of the Create action (yellow) is not the same as the incoming ledger of the non-consuming Exercise action forc-> ExeNBcch1->tf2-> ExeNBcch2->tf3-> ExeBcch3
ch1 (green). Accordingly, the subgraph without the tf1 vertex is not multi-ledger consistent for c even though it is a multi-ledger causality graph.
Definition »Consistency for a multi-ledger causality graph«
Let X be a subset of actions in a multi-ledger causality graph G. Then G is multi-ledger consistent for X (or X-multi-ledger consistent) if G is multi-ledger consistent for all contracts c on the set of actions on c in X. G is multi-ledger consistent if G is multi-ledger consistent on all the actions in G.
There is no multi-ledger consistency requirement for contract keys yet. So interoperability does not provide consistency guarantees beyond those that come from the contracts they reference. In particular, contract keys need not be unique and NoSuchKey actions do not check that the contract key is unassigned.
| contract | maximal chains |
|---|---|
Iou Bank A | Create -> Fetch -> Exercise |
ShowIou A P Bank | Create -> Exercise |
Counteroffer A P Bank | Create -> Exercise |
Iou Bank P | Create |
PaintAgree P A | Create |
Minimality and Reduction
When edges are added to anX-multi-ledger consistent causality graph such that it remains acyclic and transitively closed, the resulting graph is again X-multi-ledger consistent. The notions minimally consistent and reduction therefore generalize from ordinary causality graphs accordingly.
Definition »Minimal multi-ledger-consistent causality graph«
An X-multi-ledger consistent causality graph G is X-minimal if no strict subgraph of G (same vertices, fewer edges) is an X-multi-ledger consistent causality graph. If X is the set of all actions in G, then X is omitted.
Definition »Reduction of a multi-ledger consistent causality graph«
For an X-multi-ledger consistent causality graph G, there exists a unique minimal X-multi-ledger consistent causality graph reduce``X``(G) with the same vertices and the edges being a subset of G. reduce``X``(G) is called the X-reduction of G. As before, X is omitted if it contains all actions in G.
Since multi-ledger 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 is X-consistent, then so is the topological sort, as topological sorting merely adds edges.
From Multi-ledger Causality Graphs to Ledgers
Multi-Ledger causality graphsG are linked to ledgers L in the Daml Ledger Model via topological sort and reduction.
- Given a multi-ledger causality graph
G, drop the incoming and outgoing ledger annotations and all transfer vertices, topologically sort the transaction vertices, and extend the resulting list of transactions with the requesters to obtain a sequence of commitsL. - Given a sequence of commits
L, use the transactions as vertices and add an edge fromtx1totx2whenevertx1’s commit precedestx2’s commit in the sequence. Then add transfer vertices and incoming and outgoing ledger annotations as needed and connect them with edges to the transaction vertices.
c, then the corresponding ledger is consistent for the contract c, too. However, a multi-ledger-consistent causality graph does not yield a consistent ledger because key consistency may be violated. Conversely, a consistent ledger does not talk about the incoming and outgoing ledger annotations and therefore cannot enforce that the annotations are consistent.
Ledger-aware Projection
A Participant Node maintains a local ledger for each party it hosts and the Update Service outputs a topological sort of this local ledger. When the Participant Node hosts the party on several ledgers, this local ledger is an multi-ledger causality graph. This section defines the ledger-aware projection of an multi-ledger causality graph, which yields such a local ledger. Definition »Y-labelled action« An action with incoming and outgoing ledger annotations is Y-labelled for a setY if its incoming or outgoing ledger annotation is an element of Y.
Definition »Ledger-aware projection for transactions«
Let Y be a set of Daml ledgers and tx a transaction whose actions are annotated with incoming and outgoing ledgers. Let Act be the set of Y-labelled subactions of tx that the party P is an informee of. The ledger-aware projection of tx for P on Y (P-projection on Y) consists of all the maximal elements of Act (w.r.t. the subaction relation) in execution order.
Every action contains all its subactions. So if
act is included in the P-projection on Y of tx, then all subactions of act are also part of the projection. Such a subaction act' may not be Y-labelled itself though, i.e., belong to a different ledger. If P is an informee of act', the Participant Node will mark act' as merely being witnessed on P’s transaction stream, as explained below.Iou ledger (yellow) and the painting ledger (green). Here, the projections on the green ledger include the actions of the yellow ledger because a projection includes the subactions.
act be a transfer action annotated with an incoming ledger and/or an outgoing ledger. The projection of act on a set of ledgers Y removes the annotations from act that are not in Y. If the projection removes all annotations, it is empty.
The projection of act to a party P on Y (P-projection on Y) is the projection of act on Y if P is a stakeholder of the contract, and empty otherwise.
Definition »Multi-Ledger consistency for a party«
An multi-ledger causality graph G is consistent for a party P on a set of ledgers Y (P-consistent on Y) if G is multi-ledger consistent on the set of Y-labelled actions in G of which P is a stakeholder informee.
The notions of X-minimality and X-reduction extend to a party P on a set Y of ledgers accordingly.
Definition »Ledger-aware projection for multi-ledger causality graphs«
Let G be a multi-ledger consistent causality graph and Y be a set of Daml ledgers. The projection of G to party P on Y (P-projection on Y) is the P-reduction on Y of the following causality graph G', which is P-consistent on `Y`:
- The vertices of
G'are the vertices ofGprojected toPonY, 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.
G is a multi-ledger consistent causality graph, then the P-projection on Y is P-consistent on Y, too.
For example, the multi-ledger causality graph for the split paint counteroffer workflow is projected as follows:
- In Alice’s projection on the green ledger, Alice witnesses the archival of her
Iou. As explained in theinterop-ordering-guaranteesbelow, the Exercise action is marked as merely being witnessed in the transaction stream of a Participant Node that hosts Alice on the green ledger but not on the yellow ledger. Similarly, the Painter merely witnesses the Create of hisIouin the Painter’s projection on the green ledger. - In the Painter’s projections, the
ShowIoutransactiontx3is unordered w.r.t. to theCounterOfferacceptance intx4like in the case of ordinary causality graphs. The edgetx3->tx4is removed by the reduction step during projection.
interoperable-causality-graph-linear. The A-projections on the yellow and green ledger look as follows. The white color indicates that a transfer action has no incoming or outgoing ledger annotation. That is, a Leave action is white on the right hand side and an Enter action is white on the left hand side.
Ledger API Ordering Guarantees
The Update Service and the State Service are derived from the local ledger that the Participant Node maintains for the party. LetY be the set of ledgers on which the Participant Node hosts a party. The transaction tree stream outputs a topological sort of the party’s local ledger on Y, with the following modifications:
- Transfer actions with either an incoming or an outgoing ledger annotation are output as Enter and Leave events. Transfer actions with both incoming and outgoing ledger annotations are omitted.
- The incoming and outgoing ledger annotations are not output. Transaction actions with an incoming or outgoing ledger annotation that is not in
Yare marked as merely being witnessed if the party is an informee of the action. - Fetch nodes and NoSuchKey are omitted.
CreatedEvents, ArchivedEvents, and the Enter and Leave actions that correspond to Create, consuming Exercise, Enter and Leave actions in transaction trees on the transaction tree stream where the party is a stakeholder of the affected contract and that are not marked as merely being witnessed.
Similarly, the State Service provides the set of contracts that are active at the returned offset according to the flat transaction stream. That is, the contract state changes of all events from the transaction event stream are taken into account in the provided set of contracts.
The ordering guarantees for single Daml ledgers extend accordingly. In particular, interoperability ensures that all local ledgers are projections of a virtual shared multi-ledger causality graph that connects to the Daml Ledger Model as described above. The ledger validity guarantees therefore extend via the local ledgers to the Ledger API.