How a payment travels
A payment in Dassie is not one transfer. It is many small packets, each passed from node to node and either paid or refused on the way. This page follows them from your node to the person you pay.
On this page
Three kinds of packet
Dassie speaks Interledger, and every payment travels in Interledger packets. There are three kinds.
- Prepare asks the next node to pass some money on. It carries an amount, the address it is for, a time it expires, and a lock: the SHA-256 hash of a 32-byte secret. In effect it says: "I will pay you this much if you show me the secret that opens this lock before this time."
- Fulfill is the answer that carries the secret. Whoever holds it can prove the packet arrived.
- Reject is the answer that says no. It carries a code and the address of the node that refused. A code starting with F means the packet will never get through as it is, T means try again later, and R means it ran short on the way, most often of time. Error codes lists the ones Dassie sends.
Only the two ends of a payment can make the secret. The nodes in between cannot make one up, so a Fulfill is proof that the packet reached the person you pay.
One payment, many packets
Your node does not send the whole amount in one packet. It uses STREAM, the Interledger protocol that splits a payment into packets, encrypts what travels in them, and has the receiver report what arrived. Each payment gets a STREAM connection of its own.
- You ask to pay. The other wallet hands your node what it needs to reach the receiver, usually through Open Payments: an address and a secret the two ends share.
- Your node quotes. It sends a few probes, packets the receiver refuses on purpose, to measure how much arrives at the other end. That shows you the rate and the fees before any money moves.
- Your node sends. It keeps several packets in flight at once, sends faster while they get through and slows down when they are refused. Every packet must deliver at least the rate of the quote, or it fails.
- The receiver reports back. Every answer from the receiver, Fulfill or Reject, tells your node how much the receiver has taken so far and how much more it will take. A refusal from a node along the way says only why it refused.
- The payment ends once the receiver has what it asked for, within a tiny tolerance for rounding, or once your node has sent the amount you set, or at the payment's deadline. It ends only once none of its packets is still in flight, so what it says it sent is final.
A refused packet costs nothing but time: its money goes again in a later packet, which may take another path. Small packets keep what any one node can lose small, and many of them spread a payment over many paths.
Hop by hop
Between your node and the receiver's are the peers in between, each of them someone else's node. A packet goes like this.
- Your node sends a Prepare to one of its peers. In its books, the amount is now pending: set aside, not yet gone.
- The peer checks the packet: that it has not expired, is not too large, fits what you may owe it, and still carries money after its fee. Then it books pending transfers of its own and sends a Prepare on to the next node, expiring a little earlier than the one it took, so the answer has time to come back.
- This repeats until the packet reaches the receiver's node, whose STREAM receiver takes it if it belongs to a payment that is still open, and answers with a Fulfill.
- The Fulfill travels back the way the Prepare came. As it passes, each node posts its pending transfers: now the money has moved, in that node's books.
- A Reject, or no answer before the packet expires, voids them instead. Nothing moved.
Each node keeps its own books and decides from them alone. It never waits for its neighbors to agree, and a Fulfill it booked stays booked, whatever happens upstream.
Why it works this way and why a Fulfill is final: own Fulfills
Which way a packet goes
A node picks each packet's next hop among the peers that lead toward its destination, drawn at random and weighted by the fees each has earned it lately, with a small share of draws spread evenly so that new peers get a chance. Nothing ties a payment to one path. A node never sends a packet back to the peer it came from.
Fees and conversion
A node charges a fee only on what passes from one peer to another. Your own node never charges you for your own payments. Fees round down, so a packet too small to carry one passes free.
Where a packet arrives in one asset and leaves in another, such as XRP in and test dollars out, the node in the middle converts it at its own rates. Your own packets never convert at your node: a payment leaves on the ledger you pay from. Exchange rates says how a node prices that.
Peers also trade with each other this way. In a swap, a node sends its peer a packet over one hub, and the peer converts it at its own rates and sends it straight back over another, so the node gets one asset for the other. A core node swaps by itself when a peer's prices bring it back toward balance and pay for the swap. A node without a hostname swaps by itself only toward the targets you set, none by default, and any node swaps when you ask it to.
Limits along the way
Each node protects itself with a few limits. When a packet hits one, it is refused, and STREAM adjusts.
| Limit | What it bounds | When a packet hits it |
|---|---|---|
| The largest packet | The most one packet may carry | F08, with the most it takes, and the sender makes its packets smaller |
| Money in flight | What packets in flight with one peer carry, on each hub the two share and each way: two and a half of the largest packets | T05, and the sender backs off |
| Room | What a peer may owe the node: the credit it gives that peer | T04, and the sender backs off until the peers settle |
The cap on money in flight is there because a node that crashes with packets in flight never learns which of them were paid. Each one can leave two peers' books apart by its amount, so the cap bounds what a crash can cost.
Settling up
Packets move money in the nodes' books, not on a ledger. After a while one peer owes another. Before what it owes reaches the credit it was given, the peer it owes asks it to settle, and it pays through the settlement hub of that asset that the two share. How that works is on Settlement hubs, and how peers find each other and how much they let each other owe is on Peers and holds.
Watch it happen
The STREAM Toy runs a payment across a simulated network in your browser, packet by packet, with Dassie's own STREAM code. To send and receive STREAM payments from your own app, read STREAM on Dassie.
The connector in the spec and STREAM in the spec hold every rule