Skip to main content

Canton Network

Rocky settles on Canton Network MainNet: spot fills between customer accounts are delivered atomically (DvP) between the parties' wallets, every order event and every fill (house included) is committed to the ledger once per epoch, perpetual fills are anchored on-chain in batches, and deposits, withdrawals and the proof of solvency can all be verified against the ledger. This page introduces Canton's core concepts and Rocky's current role in the network.

1. What is Canton Network​

Canton Network is a privacy-first public network for regulated financial assets, designed by Digital Asset and built on the Daml smart-contract language.

Compared to global-shared-ledger chains:

DimensionEthereum / SolanaCanton Network
Data visibilityEverything publicEach contract is only visible to its stakeholders (privacy by default)
State synchronizationWhole-network consensus on a single ledgerMultiple Synchronizers each arbitrate independently; cross-app interactions settle across them
Smart contract modelEVM account modelDaml contracts (multi-signatory + explicit stakeholders)
Regulatory friendlinessHard to comply when everything is publicBuilt-in privacy + auditability — friendly to financial institutions

Canton fits use cases like:

  • Tokenization of regulated assets (equities, bonds, funds, stablecoins)
  • B2B on-chain settlement (clearing houses, custodians, market makers)
  • Apps that need provable settlement + data isolation (Rocky is one)

2. Core concepts​

2.1 Party​

The basic identity unit in Canton. A Party can be a person, an institution, an application, a custodian, etc. Each has a unique id:

alice::1220ca15423a1b049bf8e84132360f246057aa18f5e9e36a77db535b75bd287cceff
^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
party hint participant fingerprint suffix
  • Party hint — human-readable prefix, chosen by the app or wallet that creates the party
  • Suffix — key fingerprint of the Participant node hosting the party; it differs per wallet / validator

Rocky does not allocate parties for users. A user signs in with a Canton wallet party they already control: call POST /v1/wallet/challenge to get a challenge message, sign it with the wallet key, then submit it to POST /v1/wallet/verify. Rocky verifies the signature and binds that party to the trading account. The supported wallet providers are listed by GET /v1/wallet/providers (Rocky Wallet, Console, Loop, Send).

2.2 Contract​

A Daml contract is a data structure with an explicit stakeholder list. Each contract must declare:

  • Signatory — parties that must agree on creation and archival
  • Observer — parties that can read but not modify
  • Controller — parties that can exercise a choice (action)

Below is the DepositIntent template Rocky actually deploys (daml/perp-custody). The user declares a deposit; the exchange exercises Accept to credit it:

template DepositIntent
with
exchange : Party -- observer: Rocky exchange party
user_handle : Party -- signatory: user party
user_id_hex : Text
asset : Text
amount : Decimal
chain_tx_id : Text
created_at : Time
where
signatory user_handle
observer exchange
ensure amount > 0.0

choice Accept : ContractId PlatformAccount
with
platform_account_cid : ContractId PlatformAccount
controller exchange
do
exercise platform_account_cid Credit with
delta = amount
chain_tx_id = chain_tx_id

Daml templates Rocky currently deploys: ExchangeAuthority, PlatformAccount, FeeCollectorAccount, PerpTradeCustody, DepositIntent, WithdrawalReceipt, RockyEpochCommitment. Spot DvP settlement and CC transfers do not use private templates; they go through the public Canton Token Standard interfaces.

Key property: a contract is only visible to its stakeholders. Other parties on the same Synchronizer never see it. This is Canton's "privacy by default".

2.3 Synchronizer​

Comparable to a "blockchain" in Ethereum terms, except that multiple Synchronizers coexist. Each Synchronizer:

  • Orders and reaches consensus on the state changes of contracts within it
  • Is run by a set of Sequencer + Mediator nodes (a single operator or a decentralized group)
  • Interoperates with other Synchronizers via the Canton Network Protocol

Rocky connects to the Global Synchronizer on Canton MainNet (global-domain::1220b1431ef2…, operated by the Splice DSO).

2.4 Participant node​

A Party is never "on-chain" by itself. It must be hosted by a Participant node, which is what actually talks to the Synchronizer.

Rocky backend (canton-bridge) User wallet (Console / Loop / Send …)
↓ JSON Ledger API v2 ↓
Rocky Validator ←→ Global Synchronizer ←→ Wallet's Validator
↓ ↓
Party: Rocky exchange Party: user

Rocky runs its own Validator (api.validator.rocky.exchange), which hosts the exchange party and its operator / shadow parties. User parties are hosted by the validator behind their wallet, not on Rocky's node; users who pick Rocky Wallet use the Splice wallet that ships with Rocky's validator.

2.5 Validator​

A Validator is the standardized participant deployment provided by the Splice project: Participant + wallet app + OAuth integration.

How Rocky's backend talks to its Validator:

  • JSON Ledger API v2 to submit Daml commands and subscribe to the update stream
  • Validator API to read wallet views such as Holdings / balances
  • Auth0 machine-to-machine (M2M) tokens to authenticate backend services; Auth0 is not part of user login — user identity comes from the wallet-signature binding in §2.1

3. Privacy model​

Canton enforces privacy at three levels:

  1. Contract level — the payload is visible only to signatories + observers
  2. Participant level — a participant only receives contracts that involve parties it hosts (it stores nothing unrelated)
  3. Synchronizer level — the synchronizer only sees encrypted commitments (for ordering), never contract contents

Using the contracts Rocky actually writes on-chain:

  • PerpTradeCustody (perp fill batch) — signatory: Rocky exchange — visible only to Rocky
  • DepositIntent — signatory: user, observer: Rocky exchange — visible only to the user and Rocky
  • WithdrawalReceipt — signatory: Rocky exchange, observer: user — visible only to Rocky and the user
  • Spot DvP fill — two Token Standard transfers in one atomic Canton transaction — visible only to the two parties of the fill (wallet-to-wallet, or user wallet to Rocky's custody party)

Other users, other validators and the Synchronizer nodes cannot see any of this data, yet the Synchronizer still provides ordering guarantees and double-spend protection for every state change.


4. Rocky's role in Canton​

4.1 Party roles​

PartyConfigResponsibility
Rocky exchangeEXCHANGE_PARTY_IDPlatform party; signatory of PerpTradeCustody, WithdrawalReceipt, PlatformAccount; key held in KMS
Rocky operatorEXCHANGE_OPERATOR_PARTY_IDOperator party in Token Standard transfer / authorization flows
Shadow userSHADOW_USER_PARTY_IDRocky-controlled placeholder party for on-chain records that need no user-owned party
DSODSO_PARTY_IDDecentralized operator of the Global Synchronizer (Splice DSO), third party
Userheld by the walletThe user's own party, bound via /v1/wallet/verify; Rocky never holds its key

4.2 On-chain vs off-chain data​

Not every trading action goes on-chain. Rocky is off-chain matching + on-chain settlement of the key events:

DataWhereNotes
Order book, matching staterocky-backend (Postgres)High frequency; not viable on-chain
Trading-account balancesrocky-backend ledger.accountsHigh-frequency updates
Spot fills between customer accountsCanton, Token Standard DvPSettled per fill by spot-chain-settler; each fill returns a cantonUpdateId — see On-chain Settlement
Event journal: every order, cancel and fill (house included)Canton, RockyEpochCommitmentOne contract per 60 s epoch: Merkle root over the journal plus the epoch's fill records; inclusion proofs at GET /v1/chain/proof — see Epoch Commitments
Perp fill batchesCanton, PerpTradeCustodysettlement-batcher flushes every 5 s or every 10 fills, submitted via canton-bridge
Deposits / withdrawalsCanton, Token Standard transfers + DepositIntent / WithdrawalReceiptSee CC Deposit Flow
Proof of solvencyDaily ledger snapshot + Merkle Sum Tree commitmentSee Proof of Solvency
User identity (Party)The participant behind the user's walletReusable across apps

4.3 What users see on-chain​

Where a Rocky user touches Canton:

  1. Login — sign a challenge with the wallet and bind the party (/v1/wallet/challenge → /v1/wallet/verify)
  2. Deposit — send a Token Standard transfer from the wallet to Rocky's exchange party; the backend observes it and credits the account
  3. Spot trading — a fill involving your account settles on-chain as a DvP (the cantonUpdateId on GET /api/v3/myTrades can be verified on the ledger), and every order and fill is additionally committed in the next epoch (GET /v1/chain/proof)
  4. Withdrawal — Rocky transfers from the exchange party to the user party and records a WithdrawalReceipt
  5. Audit — use the proof of solvency to check that your liabilities are included and reserves cover them

5. Environments​

EnvironmentCanton accessUse
ProductionCanton MainNet Global Synchronizer via Rocky's own validator (api.validator.rocky.exchange)The live api.rocky.exchange service
Local developmentCanton sandbox (single participant, offline, CANTON_AUTH_MODE=none)make canton-up in the backend repo

Rocky has no DevNet deployment. User party suffixes differ from one another, depending on the validator behind each wallet.


6. Further reading​