Blog post: A Daml ledger tells a story — it’s time to show it to everyone

A Daml-based application seems to be an ordinary state machine. Sure, the application UI only displays the current state of the system and the transition options. But the unique feature of a Daml ledger is that it stores not only the state of the system but also the state transitions. For explaining the idea of Daml ledgers and the story told by a specific ledger (and for audit, graph neural network based fraud detection, etc.), it’s a good idea to show the full picture.

This is the extended version of my former forum post with nicer visualization, using the Neo4j graph database.

I also elaborate on the difference between the causality graph explained in the Daml docs and the event graph I visualize here.

1 Like

Very nice project and post @gyorgybalazsi . I think there’s a lot of value in visualizing causality chains like this to get a better understanding of how contracts interact in practice, and where contention-driven bottlenecks occur.

Eg visualizing the same settlement workflows in an account-based Daml model with high contention on account totals vs in a purist UTXO Daml model with fine-grained individual tokens might go a long way to illustrate and teach contention and its impact on performance.

1 Like

Yes, Bernhard, that’s a good application opportunity.

A product development idea to facilitate this: adding a “cypher” option to the Ledger Export feature on top of the existing “script” option.

Cypher is the query language of the Neo4J graph database.

For this small ledger the generated Cypher code looks like this:

CREATE (Event_7_0:created {offset: 7, event_id: "7_0", template: "Asset", issuer: "Alice", owner: "Alice", name: "TV"})
CREATE (Event_8_0:exercised {offset: 8, event_id: "8_0", choice: "Give", newOwner: "Bob"})
CREATE (Event_8_1:created {offset: 8, event_id: "8_1", template: "Asset", issuer: "Alice", owner: "Bob", name: "TV"})
CREATE (Event_9_0:exercised {offset: 9, event_id: "9_0", choice: "Give", newOwner: "Alice"})
CREATE (Event_9_1:created {offset: 9, event_id: "9_1", template: "Asset", issuer: "Alice", owner: "Alice", name: "TV"})
CREATE (Event_8_0)-[:CONSEQUENCE]->(Event_8_1)
CREATE (Event_9_0)-[:CONSEQUENCE]->(Event_9_1)
CREATE (Event_8_0)-[:CONSUMING]->(Event_7_0)
CREATE (Event_9_0)-[:CONSUMING]->(Event_8_1)

With Neo4j it’s easy to analyze such graphs or slice them by ledger offset etc.

I even think that getting the ACS is faster from a graph database than a SQL db. Getting the ACS is as simple as run this query:

MATCH (c:created) WHERE NOT ()-[:CONSUMING]->(c) RETURN c

Meaning, “created” events which don’t have incoming “consuming” edges.