Menu

Design decisions

Each decision records one choice between real alternatives: why Dassie works the way it does, and what it chose not to do. Here they all are, one line each. The full text lives with the specification on GitHub.

On this page
  1. Reading a decision
  2. Engineering, testing and releases
  3. The node, its keys and its owner
  4. Peers and the network
  5. Routing, rates and fees
  6. Payments
  7. Settlement, ledgers and real money
  8. Settlement hubs

Reading a decision

A decision is a short Markdown file in spec/decisions/. Each one has the same parts:

  • Areas: the parts of Dassie it shapes.
  • Facts: what forced a choice.
  • Decision: what was chosen.
  • Accepted: what the choice costs, said plainly.
  • Rejected: the other options, and why each lost.

A decision keeps the reasons. The rules themselves are in the area docs of the specification, and the values are in the code. Read a decision before you change the rule it explains.

Decisions have names, such as own-books, and a name is never given to another decision, so code and docs can cite it for good. Older commits and issues cite some decisions by a number instead; the table of former numbers translates them.

"Not built" or "partly built" in a line means the choice is made, but the code does not do all of it yet. What is missing is on What's next.

Engineering, testing and releases

How the code is written, tested, built and shipped. The rules themselves are in Engineering, Testing, Release, Website.

build-system

A Nix flake builds CI's checks and the releases; plain cargo and node --run work locally.

crash-drift

The simulation rules out a link that crashes drifted past what it survives.

crate-by-crate-builds

CI builds the Rust workspace crate by crate.

docs-section

The docs are hand-written pages under /docs/, searched with Pagefind, and link the spec on GitHub.

granite-rocks

Kopje's rocks are granite: gray blocks with hard edges, stacked, bigger than the dassies, and the brand page says why.

named-decisions

Decisions are named, not numbered.

nix-flake-on-the-mirror

NixOS takes a release from a flake on the mirror.

no-simulations-in-tests

No test runs a simulation: a case one finds becomes a targeted test.

node-and-pnpm

Tooling on Node and pnpm, not Deno.

own-books

Each node keeps its own books.

random-seed-simulations

Simulations run continuously, from random seeds (partly built).

release-integrity

Releases are signed with minisign, checked before anything is unpacked, and roll back if they do not start.

rust-and-typescript

What runs in Rust and what in TypeScript.

tigerstyle

Engineering style: pragmatic TigerStyle and deterministic simulation.

visual-identity

Dassie's visual identity is Kopje: solid rocks, nimble dassies, first light.

website-hosting

dassie.land is a bucket behind the mirror's load balancer.

The node, its keys and its owner

Your recovery phrase, the daemon, the owner's RPC and the desktop app. The rules themselves are in Identity, Node, RPC, Desktop.

database-continuity

The database starts fresh: no data of the original implementation or the early testnet is read.

default-relay

A node without a hostname keeps the dassiepay.net front door as its relay, unless its owner names another or none.

desktop-app

The desktop app runs the node in its process and shows the wallet from the node's origin.

device-pairing

Only the owner on the node's machine pairs a device, with a secret kept in memory.

headless-setup

An owner who keeps the recovery phrase on the node's host sets the node up with dassie setup, through the node's own setup route.

phrase-format

A phrase says its realm and when it was made, and corrects its own errors.

post-quantum-node-id

A node ID commits to an SLH-DSA key beside the Ed25519 key, so that a node can prove it is itself once Ed25519 falls (proving continuity not built).

ready-after-first-step

A node is up once its engine has committed a step.

rpc-contract

One protobuf contract serves the wallet and the dassie command, with live data from streams.

secrets-at-rest

Tokens are stored only as hashes; the node key stays in plaintext, readable only by the node.

Peers and the network

How nodes find each other, talk, peer and stop peering. The rules themselves are in Network, Peer protocol.

bootstrap-network

The project runs five bootstrap nodes in one region, four of which also validate the testnet's settlement hubs.

core-and-periphery

Nodes with a public IP form the core, and nodes without one join the periphery through uplinks (design, partly built).

ended-for-room

A peering ended for room stays apart.

ending-a-peering

A node that ends a peering collects first, and pays nothing.

free-receivers-half

Free receivers take at most half of the downlinks' places, and a downlink is free until its first settlement.

A downlink's accounts open once value first moves with it, in room kept for it while its channel is open.

membership-economics

Bootstrap nodes list the nodes that register; registration is free and throttled until a fee is built.

names-by-earliest-commitment

A name goes to its earliest sealed commitment, held by a quorum of the bootstrap nodes' lists (design, partly built).

peer-protocol-v1

Peer protocol v1: the sender of a request is the key its connection proved.

peering-lifecycle

How a peering is requested, kept alive and ended, and when a node looks for more peers.

periphery-lists-no-neighbors

A periphery node's link state lists no neighbors, so it may keep many uplinks.

places-by-proved-key

A connection holds a place by the key it proved.

promotion-to-core

A node becomes core by registering and being promoted (not built).

protocol-upgrades

A peer-protocol version is an ALPN name, and a release speaks the one before too; version 2 is spoken alone.

quic-only

The peer protocol and the hubs' messages travel over QUIC only.

quic-over-websocket

Where UDP is blocked, a periphery node carries its QUIC packets over a WebSocket, to its uplinks and to a front door as its relay.

settlement-methods

A peering settles over every hub both nodes are in, and a packet keeps its ledger where it can.

settlement-offers

A link state offers the schemes a node takes peers on in one list, each with its scheme's own details.

Routing, rates and fees

How a node passes packets on, what it charges and converts at, and how it swaps assets with its peers. The rules themselves are in Connector, Rate feed.

connector-timing

Connector timing and packet limits: the connector waits as ILPv4 says, where the original did not.

exchange-rates

Exchange rates, fees and spread: a rate is the median of three independent sources.

open-rate-sources

A node takes its rates only from sources whose terms allow its use: XRP's from mainnet's XRP/RLUSD pool, the fiat currencies' from central banks, with no peg guard until a dollar token has a price of its own (not built).

packets-in-flight

Money in flight with a peer stays within a few packets.

passive-rebalancing

Nodes rebalance passively: inventory pricing, published prices and market makers.

peer-swaps

Nodes swap assets with their peers, priced by snapshots of ladders per asset.

route-back-is-temporary

A route that leads only back to the packet's source answers T01, not F02.

unreachable-peers

A node takes no Prepare from a peer it cannot reach.

weighted-next-hops

A packet's next hop is drawn at random among its first hops, weighted by the fees each earned us.

Payments

Open Payments and STREAM: how money is asked for, sent and received. The rules themselves are in Payments, STREAM.

close-rather-than-lower

A receiver never lowers a maximum it told: it closes a connection that no longer fits.

full-or-stopped-short

A receiver says whether it is full or stopped short.

one-address-per-asset

One wallet address per asset, booking where the asset arrives.

one-balance-per-asset

The owner holds one balance per asset, and the node manages the hub's part of it.

open-payments

Open Payments, fully, and no SPSP.

owners-share

Strangers never take the owner's share of a pool.

A payment within a tolerance of its amount is paid in full.

path-failures-retried

A sender sends money again after a too-low rate or a node's final error, until failures without progress stop it.

public-domains

Payment names live under dassiepay.net, memo types and the mirror under dassie.land.

receive-limit-alone

A receive limit alone bounds nothing: it is refused.

receive-limit-caps-delivery

A receive limit caps what payments deliver, not only what they reserve.

unusable-limits

A limit no payment can use is caught before approval.

Settlement, ledgers and real money

How peers square up on a real ledger, how a node keeps its books, and what stands between Dassie and real money. The rules themselves are in Settlement, Ledger, XRPL.

account-budgets

Core peers and downlinks each have a share of the peers' accounts, counted by the kind they were opened as.

closing-channels

A settlement channel left idle closes to disk, whatever the balance.

dsusd

A testnet dollar of our own, bought only with XRP through a pool we keep at the market.

external-assets

External assets apart from settlement schemes.

issued-assets

An issued asset's issuer is the owner's counterparty, and a dollar token pauses off its peg (transfer fees not built).

ledger-resets

A ledger below the newest seen is a reset only on the testnet, and only once its UNL validates it (the UNL's part, the network's constant as the gate and a proven absence not built).

mainnet-schemes

Mainnet has schemes of its own, and a ledger runs only in its node's realm (a live node without the test network's defaults not built).

own-fulfills

Each node books its own Fulfills.

owner-ledger

The owner's funds on each ledger are one pool with a limit, and what the node gains or loses is the owner's.

real-money

The conditions that must hold before a node takes real money.

resident-peers

A peer is in memory only while it is needed: a downlink while it is connected, a core peer while its channel is open.

scheme-names

A scheme's ID names its ledger, network and asset, and a wallet address names the asset alone.

stub-in-debug-builds

The stub scheme runs only in builds with debug assertions.

synced-before-peering

A node peers on a scheme only once it has seen its ledger.

thresholds-in-packets

A link's thresholds are counted in its largest packet.

verified-ledgers

The node books only what ledgers its own UNL validated prove (partly built).

Settlement hubs

The shared ledgers that peers settle over. The rules themselves are in Settlement hubs.

epoch-handover

Each validator set runs an epoch of its own, and a repeat finalizes an epoch's last block.

finality-after-any-outage

A hub finalizes again after any outage, in bounded memory.

hub-founding

The sponsor founds a hub over a stream of its own, and a quorum's signatures of the genesis found it.

hub-keys-by-network

A hub's keys name its network, and a validator validates on its owner's network.

hub-named-when-added

A hub scheme names its hub from the moment it is added (moving a scheme to another hub not built).

hub-protocol-version

A hub runs one version of the hub protocol, which its ID commits to (moving a hub to another version not built).

hub-scheme-names

A hub scheme's ID names its underlying ledger and its asset.

hubs-only

Peers settle only over settlement hubs.

settlement-hubs

Settlement hubs: ledgers kept by validators and backed by an escrow on the XRP Ledger (design, partly built).

token-hubs

A hub may hold an issued token; its issuer's freeze pauses it, a clawback ends it, and its fees are paid in XRP anyone may send (partly built).

A kopje of granite blocks against the sun, in veld grass; one dassie climbs its slab, one keeps lookout on top inside the sun, and one sleeps on the next rock; on a wide screen, a pair sits on a kopje to the left