Canton is a private permissioned blockchain built by Digital Asset. But wait—what do those words actually mean?
Private: Unlike Bitcoin where anyone can see every transaction, Canton hides transaction details. Only parties involved in a deal see it. Your competitor won't know you just bought 10,000 widgets.
Permissioned: Bitcoin lets anyone run a node and mine blocks. Canton says "not so fast." You need approval to join. Only validated nodes can write to the ledger. Why? Because financial institutions don't want anonymous strangers validating their trades.
Canton isn't one blockchain. It's a network of synchronized domains that can interoperate. Think of domains as separate rooms where transactions happen—but parties can walk between rooms while maintaining consistency.
You write smart contracts in DAML (Digital Asset Modeling Language). It looks like Haskell because it is based on Haskell—a functional language designed to avoid bugs through strong typing.
The key difference? In Java, authorization is just data you check at runtime. In DAML, it's enforced by the compiler and the ledger—you literally cannot submit a transaction where an unauthorized party exercises a choice.
What's happening here?
Accept lets the buyer turn the offer into an agreement.DAML's superpower: authorization is built into the language. You can't accidentally write code that lets unauthorized parties modify contracts. The compiler catches it.
DAML source → daml build → DAR file → Upload to Participant Node → Execute on Ledger
DAR (DAML Archive) is like a JAR file—compiled bytecode bundled with dependencies. The participant node's DAML engine interprets this bytecode when executing transactions.
Who runs this thing? Not Digital Asset alone. The Global Synchronizer Foundation is a non-profit that:
Think of GSF as the "board of directors" for Canton's shared infrastructure.
The heavy lifters. Large institutions like digitalasset.com, cumberland.io, and others run critical infrastructure:
| What They Run | What It Does |
|---|---|
| Sequencer Nodes | Order transactions globally. Without ordering, you get chaos—two parties could "double-spend." |
| Mediator Nodes | Coordinate transaction confirmations across participants |
| Scan Nodes | Provide APIs for querying the ledger history |
SVs have their own security policies and must meet strict uptime requirements. They're the backbone.
Smaller participants who validate transactions but don't run global infrastructure.
Requirements:
A contract is a live instance of a DAML template on the ledger. When you create in DAML, you get back a ContractId—a unique reference to that specific contract instance.
contractId <- create MyTemplate with field1 = "value"
-- contractId is now a pointer to this contract
Contract IDs are content-addressed: derived from the contract's contents. Same inputs = same ID (but you can't create duplicates—the ledger prevents it).
Contracts have lifecycles:
A domain is a synchronization point where transactions get ordered and confirmed. Canton can have multiple domains:
Transactions can span domains through domain transfers—moving a contract from one domain to another while maintaining atomicity.
A network-level concept that tracks major protocol upgrades.
| Environment | Migration ID |
|---|---|
| Devnet | 1 |
| Testnet | varies |
| Mainnet | increments with protocol upgrades |
Why does this matter? When Canton upgrades its protocol, the migration ID increments. Your application database tracks which migration it's synced to.
When a Canton node upgrade fails mid-way, your database might be in an inconsistent state. Check what was actually ingested:
No rows returned? Good news—nothing was ingested, database is clean. Roll back the binary and retry.
Rows returned? The upgrade partially completed. You'll need to either:
"Party not authorized": Your DAML choice's controller doesn't match who's submitting the command. Check your controller clauses.
"Contract not found": Either the contract was archived, or your party can't see it (not a signatory or observer).
"Domain disconnected": Your participant lost connection to the synchronization domain. Check network, check sequencer health.
Each participant runs their own node, stores their own view of contracts they're party to, and submits transactions through the synchronizer.