Paying peer to peer
In the old model, Alice pays Bob by broadcasting a Transaction to the network, and Bob finds out about it by watching his Addresses. In this section we will look at how two full-history wallets exchange a payment directly, and why that is both simpler and safer.
The examples in this section come from SpiffyVault, whose payments are built on libspiffy.
The payment flow
Section titled “The payment flow”Every payment, however it travels, follows the same four steps:
- The payee creates an invoice. Bob’s wallet derives fresh Addresses for the payment and records the amount it expects.
- The payer builds the payment. Alice’s wallet selects coins, builds and signs the Transaction, and collects its unmined ancestors and their merkle proofs into a BEEF. It does not broadcast it.
- The payer hands the BEEF to the payee, over whatever channel the two applications share.
- The payee checks and broadcasts it. Bob’s wallet checks the BEEF against its own header chain, checks that it pays what the invoice asked for, and then broadcasts it through Arcade.
Figure 1 shows this as a sequence, for two wallets that can reach each other directly.
Do note that libspiffy owns no transport. It produces the invoice and the BEEF, and it validates what it receives, but moving those between the two wallets is the application’s job. The rest of this section is about how SpiffyVault does that.
Why the payee broadcasts
Section titled “Why the payee broadcasts”It might seem odd that Bob, not Alice, broadcasts the payment. There are good reasons for it:
- Bob is the party that cares about being paid. Once Bob submits the payment, it is his broadcast. Arcade follows it to the network and into a block, and the merkle proof of Bob’s new coins comes back to Bob, with no need for anyone to look anything up.
- Bob checks it before the network sees it. A payment that doesn’t pay what the invoice asked for never reaches the network.
- Alice keeps an exit. Until the network holds the payment, Alice’s wallet holds the coins it spent in reserve. If Bob never broadcasts, Alice can cancel the payment, or reclaim her coins by spending them back to herself. A payment can also carry a deadline, after which her wallet reclaims it by itself.
It should be noted that checking a BEEF proves the payment’s ancestry is anchored in real blocks. It does not prove that Alice hasn’t also signed a different Transaction spending the same coins. That is only settled when the network accepts one of them, which is why Bob’s wallet waits for Arcade to report the payment as seen on the network before counting it as paid.
Three ways to deliver a payment
Section titled “Three ways to deliver a payment”SpiffyVault tries three ways of delivering a payment, in this order.
Live, over a direct connection
Section titled “Live, over a direct connection”When both wallets are online, Alice’s wallet opens a libp2p stream to Bob’s phone, either directly or through a relay when both phones sit behind NAT routers. Bob’s wallet answers with an invoice, and Alice’s wallet sends back the BEEF, exactly as in Figure 1.
Offline, through a mailbox
Section titled “Offline, through a mailbox”Bob’s phone isn’t always online. When the live attempt fails before any Transaction has changed hands, Alice’s wallet pays Bob without him:
- It reads Bob’s payment anchor: a public key Bob has signed and published in a document on a Ricochet server.
- It derives a fresh, one-time destination for the payment from Bob’s anchor key, using BRC-42.
- It builds the BEEF, encrypts it for Bob, and leaves it in Bob’s mailbox on the Ricochet server.
When Bob’s phone next comes online it collects the message, checks the BEEF, and broadcasts it. We look at Ricochet more closely in Overlay networks.
PeerPay, for other wallets
Section titled “PeerPay, for other wallets”Wallets built on the BSV Association’s BRC-100 stack, e.g. BSV Desktop and BSV Browser, pay each other with PeerPay: a BRC-29 payment left in a MessageBox (BRC-33), a store-and-forward server the payer reaches over an authenticated session (BRC-103). All the payer needs is the payee’s identity key. SpiffyVault speaks PeerPay too, so it can pay, and be paid by, any wallet that does.
Further reading
Section titled “Further reading”- libspiffy: Invoices & SPV: the commands behind each step of the payment flow.
- libspiffy: Deferred payments: how a payer’s coins are held, cancelled and reclaimed.

