This section addresses the question of who can request which changes.
At the core is the concept of a valid ledger; changes are permissible if adding the corresponding commit to the ledger results in a valid ledger. Valid ledgers are those that fulfill three conditions:
- Exercises and fetches on inactive contracts are not allowed, i.e. contracts that have not yet been created or have already been consumed by an exercise. A contract with a contract key can be created only if the key is not associated to another unconsumed contract, and all key assertions hold.
- Only a restricted set of actions is allowed on a given contract.
- The parties who may request a particular change are restricted.
Only the last of these conditions depends on the party (or parties) requesting the change; the other two are general.
Consistency consists of two parts:
- Contract consistency: Contracts must be created before they are used, and they cannot be used once they are consumed.
- Key consistency: Keys are unique and key assertions are satisfied.
To define this precisely, notions of “before” and “after” are needed. These are given by putting all actions in a sequence. Technically, the sequence is obtained by a pre-order traversal of the ledger’s actions, noting that these actions form an (ordered) forest. Intuitively, it is obtained by always picking parent actions before their proper subactions, and otherwise always picking the actions on the left before the actions on the right. The image below depicts the resulting order on the paint offer example:
In the image, an action act happens before action act’ if there is a (non-empty) path from act to act’. Then, act’ happens after act.
Contract consistency ensures that contracts are used after they have been created and before they are consumed.
- Definition »contract consistency«
A ledger is consistent for a contract c if all of the following holds for all actions act on c:
- either act is itself Create c or a Create c happens before act
- act does not happen before any Create c action
- act does not happen after any Exercise action consuming c.
The consistency condition rules out the double spend example. As the red path below indicates, the second exercise in the example happens after a consuming exercise on the same contract, violating the contract consistency criteria.
In addition to the consistency notions, the before-after relation on actions can also be used to define the notion of contract state at any point in a given transaction. The contract state is changed by creating the contract and by exercising it consumingly. At any point in a transaction, we can then define the latest state change in the obvious way. Then, given a point in a transaction, the contract state of c is:
- active, if the latest state change of c was a create;
- archived, if the latest state change of c was a consuming exercise;
- inexistent, if c never changed state.
A ledger is consistent for c exactly if Exercise and Fetch actions on c happen only when c is active, and Create actions only when c is inexistent. The figures below visualize the state of different contracts at all points in the example ledger.
The notion of order can be defined on all the different ledger structures: actions, transactions, lists of transactions, and ledgers. Thus, the notions of consistency, inputs and outputs, and contract state can also all be defined on all these structures. The active contract set of a ledger is the set of all contracts that are active on the ledger. For the example above, it consists of contracts Iou Bank P and PaintAgree P A.
Contract keys introduce a key uniqueness constraint for the ledger. To capture this notion, the contract model must specify for every contract in the system whether the contract has a key and, if so, the key. Every contract can have at most one key.
Like contracts, every key has a state. An action act is an action on a key k if
- act is a Create, Exercise, or a Fetch action on a contract c with key k, or
- act is the key assertion NoSuchKey k.
- Definition »key state«
The key state of a key on a ledger is determined by the last action act on the key:
- If act is a Create, non-consuming Exercise, or Fetch action on a contract c, then the key state is assigned to c.
- If act is a consuming Exercise action or a NoSuchKey assertion, then the key state is free.
- If there is no such action act, then the key state is unknown.
A key is unassigned if its key state is either free or unknown.
Key consistency ensures that there is at most one active contract for each key and that all key assertions are satisfied.
- Definition »key consistency«
A ledger is consistent for a key k if for every action act on k, the key state s before act satisfies
- If act is a Create action or NoSuchKey assertion, then s is free or unknown.
- If act is an Exercise or Fetch action on some contract c, then s is assigned to c or unknown.
Key consistency rules out the problematic examples around key consistency. For example, suppose that the painter P has made a paint offer to A with reference number P123, but A has not yet accepted it. When P tries to create another paint offer to David with the same reference number P123, then this creation action would violate key uniqueness. The following ledger violates key uniqueness for the key (P, P123).
Key assertions can be used in workflows to evidence the inexistence of a certain kind of contract. For example, suppose that the painter P is a member of the union of painters U. This union maintains a blacklist of potential customers that its members must not do business with. A customer A is considered to be on the blacklist if there is an active contract Blacklist @U &A. To make sure that the painter P does not make a paint offer if A is blacklisted, the painter combines its commit with a NoSuchKey assertion on the key (U, A). The following ledger shows the transaction, where UnionMember U P represents P’s membership in the union U. It grants P the choice to perform such an assertion, which is needed for authorization.
Key consistency extends to actions, transactions and lists of transactions just like the other consistency notions.
- Definition »ledger consistency«
- A ledger is consistent if it is consistent for all contracts and for all keys.
The above consistency requirement is too strong for actions and transactions in isolation. For example, the acceptance transaction from the paint offer example is not consistent as a ledger, because PaintOffer A P Bank and the Iou Bank A contracts are used without being created before:
However, the transaction can still be appended to a ledger that creates these contracts and yields a consistent ledger. Such transactions are said to be internally consistent, and contracts such as the PaintOffer A P Bank P123 and Iou Bank A are called input contracts of the transaction. Dually, output contracts of a transaction are the contracts that a transaction creates and does not archive.
- Definition »internal consistency for a contract«
A transaction is internally consistent for a contract c if the following holds for all of its subactions act on the contract c
- act does not happen before any Create c action
- act does not happen after any exercise consuming c.
A transaction is internally consistent if it is internally consistent for all contracts and consistent for all keys.
- Definition »input contract«
- For an internally consistent transaction, a contract c is an input contract of the transaction if the transaction contains an Exercise or a Fetch action on c but not a Create c action.
- Definition »output contract«
- For an internally consistent transaction, a contract c is an output contract of the transaction if the transaction contains a Create c action, but not a consuming Exercise action on c.
Note that the input and output contracts are undefined for transactions that are not internally consistent. The image below shows some examples of internally consistent and inconsistent transactions.
Similar to input contracts, we define the input keys as the set that must be unassigned at the beginning of a transaction.
- Definition »input key«
- A key k is an input key to an internally consistent transaction if the first action act on k is either a Create action or a NoSuchKey assertion.
In the blacklisting example, P’s transaction has two input keys: (U, A) due to the NoSuchKey action and (P, P123) as it creates a PaintOffer contract.
The conformance condition constrains the actions that may occur on the ledger. This is done by considering a contract model M (or a model for short), which specifies the set of all possible actions. A ledger is conformant to M (or conforms to M) if all top-level actions on the ledger are members of M. Like consistency, the notion of conformance does not depend on the requesters of a commit, so it can also be applied to transactions and lists of transactions.
For example, the set of allowed actions on IOU contracts could be described as follows.
The boxes in the image are templates in the sense that the contract parameters in a box (such as obligor or owner) can be instantiated by arbitrary values of the appropriate type. To facilitate understanding, each box includes a label describing the intuitive purpose of the corresponding set of actions. As the image suggests, the transfer box imposes the constraint that the bank must remain the same both in the exercised IOU contract, and in the newly created IOU contract. However, the owner can change arbitrarily. In contrast, in the settle actions, both the bank and the owner must remain the same. Furthermore, to be conformant, the actor of a transfer action must be the same as the owner of the contract.
Of course, the constraints on the relationship between the parameters can be arbitrarily complex, and cannot conveniently be reproduced in this graphical representation. This is the role of Daml – it provides a much more convenient way of representing contract models. The link between Daml and contract models is explained in more detail in a later section.
To see the conformance criterion in action, assume that the contract model allows only the following actions on PaintOffer and PaintAgree contracts.
The problem with example where Alice changes the offer’s outcome to avoid transferring the money now becomes apparent.
A’s commit is not conformant to the contract model, as the model does not contain the top-level action she is trying to commit.
Valid Ledgers, Obligations, Offers and Rights¶
Daml ledgers are designed to mimic real-world interactions between parties, which are governed by contract law. The validity conditions on the ledgers, and the information contained in contract models have several subtle links to the concepts of the contract law that are worth pointing out.
First, in addition to the explicit off-ledger obligations specified in the agreement text, contracts also specify implicit on-ledger obligations, which result from consequences of the exercises on contracts. For example, the PaintOffer contains an on-ledger obligation for A to transfer her IOU in case she accepts the offer. Agreement texts are therefore only necessary to specify obligations that are not already modeled as permissible actions on the ledger. For example, P’s obligation to paint the house cannot be sensibly modeled on the ledger, and must thus be specified by the agreement text.
Second, every contract on a Daml ledger can simultaneously model both:
- a real-world offer, whose consequences (both on- and off-ledger) are specified by the Exercise actions on the contract allowed by the contract model, and
- a real-world contract “proper”, specified through the contract’s (optional) agreement text.
Third, in Daml ledgers, as in the real world, one person’s rights are another person’s obligations. For example, A’s right to accept the PaintOffer is P’s obligation to paint her house in case she accepts. In Daml ledgers, a party’s rights according to a contract model are the exercise actions the party can perform according to the authorization and conformance rules.
Finally, validity conditions ensure three important properties of the Daml ledger model, that mimic the contract law.
Obligations need consent. Daml ledgers follow the offer-acceptance pattern of the contract law, and thus ensures that all ledger contracts are formed voluntarily. For example, the following ledger is not valid.
Consent is needed to take away on-ledger rights. As only Exercise actions consume contracts, the rights cannot be taken away from the actors; the contract model specifies exactly who the actors are, and the authorization rules require them to approve the contract consumption.
In the examples, Alice had the right to transfer her IOUs; painter’s attempt to take that right away from her, by performing a transfer himself, was not valid.
Parties can still delegate their rights to other parties. For example, assume that Alice, instead of accepting painter’s offer, decides to make him a counteroffer instead. The painter can then accept this counteroffer, with the consequences as before:
Here, by creating the CounterOffer contract, Alice delegates her right to transfer the IOU contract to the painter. In case of delegation, prior to submission, the requester must get informed about the contracts that are part of the requested transaction, but where the requester is not a signatory. In the example above, the painter must learn about the existence of the IOU for Alice before he can request the acceptance of the CounterOffer. The concepts of observers and divulgence, introduced in the next section, enable such scenarios.
On-ledger obligations cannot be unilaterally escaped. Once an obligation is recorded on a Daml ledger, it can only be removed in accordance with the contract model. For example, assuming the IOU contract model shown earlier, if the ledger records the creation of a MustPay contract, the bank cannot later simply record an action that consumes this contract:
That is, this ledger is invalid, as the action above is not conformant to the contract model.