Daml is largely powered by its ledger model, so understanding Daml’s ledger model is core to understanding Daml as a whole.
Here we present a high level overview of how Daml’s ledger model works. If you already know this and instead want a deep and technical explanation of the Daml ledger model then please refer to our very extensive documentation.
Why is Daml’s ledger model so important to understand?
The ultimate goal of Daml is to allow multiple parties to each own and control their own data while simultaneously being able to interoperate with each other with perfect synchronization and no reconciliation process. In order to achieve this when programming Daml you need to take care to think about rights and obligations over every part of your code (ie. who can see, and do what).
At first this seems like a restriction because as programmers we are very used to having absolute control over the entire codebase, and database of our applications. However with some understanding this “restriction” quickly evolves into an easy way to specify the requirements of your application and ensure that there is no chance for an inconsistency, unintentional obligation, or incorrect specification to occur between different parts of a large and complex application. In Daml your code truly becomes your specification.
What Is a Ledger?
To understand Daml’s ledger we first need to know what we mean when we talk about a “ledger” in general. A ledger is simply a database that stores a series of updates or commits.
If you’re familiar with SQL you might know that when a transaction is committed to the database that transaction updates some data within the database, and the transaction is typically erased shortly after. You might also know that SQL databases typically save enough data (ie. a savepoint) so that any transaction can be rolled back.
Daml is similar, except every transaction is kept around for a much longer period of time, so new updates to values in your database replace old values, but do not erase them. This will sound familiar to you if you’ve ever used an event store.
Hopefully that makes sense but here’s a small table illustrating the difference as well. We’re limited in how we can represent this in markdown but imagine you have two equivalent databases that are each storing a single value. After 3 transactions changing that value you then go and take a view of your SQL and Daml databases. What you’d see is the below.
Transaction | SQL | Daml |
---|---|---|
{value:4} | ||
{value: 13} | ||
{value:7} | 7 | 7 (active) |
Above you can see that our SQL database erased the old values (4, 13
), and our Daml database replaced them in turn but didn’t erase them. Instead it “archived” them which for Daml means that the value persists but can no longer be used. More on why that is later.
Why keep “old” data?
Daml is designed to allow multiple different parties to interact in such a way that they can each get their own view of the data on a Daml ledger, and not have to explicitly trust any one party to give them the current state; instead they are able to ask for data and derive it themselves. This allows for each party to own and store their own data and interact with other parties without needing to have expensive and time consuming reconciliation processes, or offload it to a trusted third party.
A visual may help, so imagine a change in who could see the values in our earlier example. For Alice in the revised example below the last number she will have seen is 13
getting archived (or 7
being created in some cases). Her view of the state effectively stops here, and cannot be easily discarded by Bob or otherwise Bob wouldn’t know how he got to the current state.
Global view*
*No one actually gets a global view, this is just for demonstration. Note row 3 where the observer of the contract changes from Alice to Bob.
Transaction | SQL | Daml |
---|---|---|
{value:4, observer: Alice} | ||
{value: 13, observer: Alice} | ||
{value: 13, observer: Bob} | ||
{value:7, observer: Bob} | ||
{value:22, observer: Bob} | 22 | 22 (active) |
Alice’s view
Transaction | SQL | Daml |
---|---|---|
{value:4, observer: Alice} | ||
{value: 13, observer: Alice} | ||
{value: 13, observer: Alice} |
Bob’s view
Transaction | SQL | Daml |
---|---|---|
{value: 13, observer: Alice} | ||
{value:7, observer: Bob} | ||
{value:22, observer: Bob} | 22 | 22 (active) |
This is a simplified example, but imagine an IOU between two parties being passed to a third, the history of these swaps is crucial to the value of the IOU.
Putting it all together
So in short every Daml Ledger is a series of commits creating, archiving, and replacing contracts. The specific commits a party is able to view depends on the permissions they have on a contract at the time of the commit. This enables what we call a Virtual System of Record, where each party sees the set of data relevant to them and nothing else. Ultimately this enables each party to:
- Have perfect synchronization of data
- Interact with other parties while preserving privacy
- Avoid time consuming reconciliation processes