BRC-246: Session Upgrade: BRC-33 Messages over WebRTPay
Brandon Cryderman / HandCash (brandongcryderman@gmail.com)
Status: Draft (proposed number, not a BSVA assignment)
Abstract
This BRC lets two online wallets, or two installs of one account, carry BRC-33 messagebox traffic on a direct WebRTC data channel. The connection is the one webrtpay/1 (WebRTPay protocol reference) already defines for direct payments, used unchanged: the same signalling envelopes, presence check, channel framing and identity handshake. This BRC adds only what webrtpay/1 lacks for messages: a messages purpose, device addressing for installs that share an identity key, and two session messages, msg and ack.
The messagebox remains the rendezvous and the offline inbox. The channel carries the same message bodies the box would, and never carries custody.
Motivation
A messagebox exists because the other wallet is often offline, firewalled, or unable to keep a listener. When both wallets are online, routing every chat line, remittance card and coordination message through a store-and-forward host adds latency for nothing.
webrtpay/1, shipped as @bsv/webrtpay in the BSV TypeScript stack, already solves the hard parts for payments: NAT traversal, a presence check that answers in about two seconds, end-to-end encrypted signalling, a channel bound to both identity keys through BRC-100 signatures, an optional relay and TURN. A second protocol for the same connection would split wallets into two groups that cannot reach each other. This BRC therefore reuses that connection and defines only the messaging layer on top of it.
Relationship to other documents
| Concern | Document |
|---|---|
| Connection: signalling envelopes and their encryption, knock and ring, ICE, channel framing, identity handshake, relay | webrtpay/1 (reference) §3 to §5, §7 to §9 |
| Messages carried | BRC-33, each body sealed per BRC-78 |
| Keys and signatures | BRC-100 |
| Coordination between installs of one account | Draft BRC-249 (#311) |
Section numbers such as webrtpay/1 §7.4 refer to the reference at the commit linked below.
Specification
The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" are to be interpreted as described in RFC 2119.
1. Scope
This BRC covers messages already sent over BRC-33: chat, remittance cards, token deliveries and similar notices, and coordination between installs of one account such as BRC-249 release requests. It does not cover coin selection, signing or broadcast. An on-chain output remains the only proof of payment or item custody. A payment by itself uses webrtpay/1's payment purpose, not this one.
2. Endpoints
An endpoint is one install: an identity key and a device, a random identifier of 1 to 128 characters from [A-Za-z0-9._-] that the install keeps for its lifetime. Two endpoints may share an identity key, as installs of one account do; they MUST then differ in device. The device SHOULD NOT be derived from any key or hardware identifier.
3. Signalling
Signals are webrtpay/1 signalling envelopes (§7.1 to §7.3), encrypted with BRC-100 encrypt under protocol [2, "webrtpay signaling"] exactly as there, with these differences:
- Purpose. The plaintext's
purposeis"messages". - Devices. The plaintext carries
fromDevice, the sender's device, andtoDevice, the recipient's device. In aknockorofferto another identity,toDeviceMAY be empty, meaning whichever install answers. It MUST be set whentoequalsfrom, and in everyring,answerandreject, where it is the dial'sfromDevice. - Box. On a messagebox carrier, signals go in box
webrtpay_messages, never inwebrtpay_signals. A wallet that implements only payments never lists that box, so it never decrypts a signal it would refuse. A relay carrier (webrtpay/1§8) carries them unchanged.
A receiver opens a signal as webrtpay/1 §7.4 does, accepting purpose "messages" in step 2 and checking the device fields before anything else:
- It ignores a signal whose
fromis its own identity and whosefromDeviceis its own device. - It ignores a signal whose
toDevicenames another device, and MUST NOT acknowledge it on the messagebox, so the addressed install still finds it. - It acknowledges every other signal once it has processed it.
An install applies these rules even when it cannot open a data channel, so it never consumes signals meant for its siblings. Installs sharing an identity share its box, so these rules are what lets each one find its own.
4. Dialing and admission
Dialing follows webrtpay/1 §7.5: knock, ring, offer, answer, with its presence and dial timeouts and its network binding. A dial that ends peer_unreachable, timeout or rejected sends its messages through the messagebox.
When the messagebox is polled rather than pushed (BRC-33 listMessages), a reply can only come after the peer's next read. A dialer on such a carrier adds the peer's poll interval to both the presence and the dial timeout, and a polling wallet reads its signalling box at least every 2.5 s while it receives and every second while it dials.
A wallet SHOULD ring and answer only identities the user has exchanged messages with, and its own installs, and otherwise answer a knock with reject not_receiving or not at all. Intake limits follow webrtpay/1 §7.6.
An endpoint has at most one messages session with another endpoint. When installs of one account dial each other at once, the one whose identityKey + "\n" + device sorts lower keeps its dial and the other answers it.
5. Session messages
After the identity handshake (webrtpay/1 §5), the session carries webrtpay/1 frames (§4) whose objects are:
{ "t": "msg", "id": "<1–64 characters>", "body": "<the body the messagebox would have carried>" }
{ "t": "ack", "id": "<the msg id>" }
and webrtpay/1's error and bye (§6.4). Any other t is a protocol error, as in webrtpay/1 §6.
- The receiver MUST pass
bodyto the same ingest path as a messagebox message from the identity the handshake proved, and sendackafter ingest accepts it. - A
msgMUST NOT exceed 256 KiB; a larger body goes through the messagebox. - If the sender receives no
ackwithin one second, it MUST close the session and send that message through the messagebox. A body can therefore arrive twice, once per path, so ingest MUST treat a repeat as it treats a repeated messagebox delivery. - An
ackacknowledges delivery of a message, never a payment.
6. Lifetime
A session ends when its channel closes, ICE fails, or either side sends bye. Messages then go through the messagebox until a new dial completes. A wallet SHOULD close a session that has been idle for ten minutes, and MUST close its sessions when it locks or switches account.
7. What this is not
- Not a replacement for BRC-33. First contact, offline peers and failed dials use the messagebox.
- Not a custody channel.
- Not history sync. Installs of one account may hold a session to carry coordination messages, not to merge state continuously.
- Not a listener requirement. Neither side opens a port.
Security considerations
- Authentication and encryption are
webrtpay/1's: each side signs a transcript of both DTLS fingerprints, both nonces and both identity keys with a BRC-100 key, so a messagebox host, STUN server or TURN relay cannot read or redirect the channel. Eachbodykeeps its own BRC-78 envelope as well, exactly as on the box. - Address exposure. An offer or answer reveals the sender's public address, and possibly local ones, to its recipient only, since signals are encrypted to it.
webrtpay/1gathers no ICE before a ring, so a knock discloses nothing. STUN servers learn a wallet's public address; a TURN relay learns both endpoints' addresses and sees only encrypted traffic. This is why §4 limits who is answered. - Abuse. Anyone can post signals to a wallet's
webrtpay_messagesbox. Answering only known identities andwebrtpay/1's intake limits bound the work.
Rationale
- Why build on
webrtpay/1. It is the WebRTC connection the BSV stack ships, with a byte-level reference and test vectors. Reusing it means one connection for payments and messages, one handshake to audit, and wallets that interoperate. - Why a separate purpose and box.
webrtpay/1receivers refuse any purpose butpaymentand close on unknown session messages. Its own purpose and box keep payment-only wallets untouched, and let a wallet that implements both route each signal without trial decryption. - Why devices. Two installs of one account have the same identity key. The device tells them apart in addressing, in simultaneous dials and in acknowledgement, which is what lets BRC-249 coordinate a move over a direct session.
Implementation
@bsv/webrtpay (bsv-blockchain/ts-stack) implements the connection. HandCash Desktop and Mobile implement an earlier revision of this BRC, which signed session descriptions directly, and are moving to this one.
References
webrtpay/1: WebRTPay protocol reference,@bsv/webrtpay- BRC-33: PeerServ Message Relay Interface
- BRC-78: Serialization Format for Portable Encrypted Messages
- BRC-100: Wallet-to-Application Interface
- Draft BRC-249 (#311): Vault Account Holding Across Devices
- RFC 8445: Interactive Connectivity Establishment (ICE)
- RFC 8831: WebRTC Data Channels