Important
An update regarding Raven in general and Betanet, which we highly recommend reading: https://x.com/ravendevteam/status/1971816736052650057
Important
Version 1.2 of the Betanet specification has been proposed and you can view the proposal here. This version significantly improves the specification and corrects many of the problems found in the current version. Please read it over and provide feedback if you have any.
Normative document. All requirements marked MUST, MUST NOT, or SHALL are mandatory for compliance.
Betanet is a fully decentralised, censorship-resistant network intended to replace the public Internet. This revision finalises covert transport indistinguishability, removes linkability vectors, specifies liveness for naming, hardens governance and bootstrap economics, and standardises adaptive calibration.
- Multi-byte integers: unsigned big-endian.
varint: QUIC variable-length integer (RFC 9000 §16).- Unless stated, sizes are in bytes.
- Binary examples use hexadecimal.
| Purpose | Primitive |
|---|---|
| Hash | SHA-256 (32) |
| AEAD | ChaCha20-Poly1305 (IETF, 12-B nonce, 16-B tag) |
| KDF | HKDF-SHA256 |
| Signatures | Ed25519 |
| Diffie–Hellman | X25519 |
| Post-quantum hybrid | X25519-Kyber768 (hybrid) |
PQ requirement. From 2027-01-01, the inner key agreement (L2 §5.3) MUST be hybrid X25519-Kyber768. The outer TLS handshake (L2 §5.1) MUST mirror the front origin and MUST NOT advertise PQ that diverges from the origin’s canonical fingerprint.
Algorithm agility. Implementations MUST expose a registry of cryptographic parameters keyed by OIDs; future substitutions MUST be negotiated via governance (L7) without changing wire formats where lengths permit.
| Layer | Function |
|---|---|
| L0 | Access media (any IP bearer: fibre, 5G, sat, LoRa, etc.) |
| L1 | Path selection & routing (SCION + HTX-tunnelled transition) |
| L2 | Cover transport (HTX over TCP-443 / QUIC-443) |
| L3 | Overlay mesh (libp2p-v2 object relay) |
| L4 | Optional privacy hop (Nym mixnet) |
| L5 | Naming & trust (self-certifying IDs + 3-chain alias ledger) |
| L6 | Payments (federated Cashu + Lightning) |
| L7 | Applications |
0 1 2 3
+-------+-------+-------+-------+
|Ver=0x2|Reserved| Type |
+-------------------------------+
| Total Header Length |
+-------------------------------+
| Payload Length |
+-------------------------------+
| Path Segment 0 … |
+-------------------------------+
- Ver MUST be
0x02. - Type MUST be
0x01(single path) or0x03(path list). - Each AS-hop signature in every segment MUST verify before forwarding; otherwise drop.
Gateways bridging non-SCION segments MUST encapsulate SCION packets inside an HTX control session (L2) between gateways:
-
Establish an HTX session using §5 (origin-mirrored TLS).
-
Negotiate a Transition Control Stream opened by the gateway acting as the server, with stream_id=2 (first even stream).
-
The control stream payload is a single CBOR map:
{ prevAS, nextAS, TS, FLOW, NONCE, SIG }where
TS= unix-sec,FLOW= 8B random,NONCE= 8B random, andSIG= Ed25519 over(prevAS ‖ nextAS ‖ TS ‖ FLOW ‖ NONCE ‖ "bn-t1"). -
Gateways MUST verify
TSwithin ±300 s, reject duplicate(FLOW,TS)for 2 h, and apply per-peer token buckets. -
SCION payloads are carried on subsequent HTX streams. No per-packet transition header appears on the public wire.
-
Gateways MUST close and re-establish the control stream on rekey (§5.3). Out-of-date control streams are invalid.
Public-Internet requirement. The legacy on-wire transition header is PROHIBITED on public networks. It MAY be used only on private, administratively controlled links (§11).
- Maintain up to 3 disjoint validated paths per peer.
- Switch within 300 ms when an alternative validated path exists.
- Probe with exponential back-off (min 1 s, max 60 s); MUST NOT exceed 1 probe per destination per 10 s under persistent loss.
- Clients MUST mirror the front origin’s fingerprint class (JA3/JA4 family, ALPN set, extension order, GREASE, H2 SETTINGS, H3 availability).
- A per-connection calibration pre-flight to the same origin (or same CDN POP if indicated) MUST be performed before inner handshake; any deviation MUST fail closed.
- Tolerances: ALPN set and order MUST match exactly. Extension order MUST match exactly. H2 SETTINGS values MUST be within ±15 % of calibrated origin values where the origin publishes variable ranges; otherwise MUST match exactly.
- POP selection: If the origin presents geo/POP variance, clients MUST calibrate against the same POP as the target connection as indicated by authoritative DNS co-location or CDN route headers; otherwise calibration MUST be repeated until equality is achieved.
- ALPN selection MUST match the origin; fixed global distributions are PROHIBITED.
- Session resumption MUST follow origin policy; 0-RTT MUST NOT be used for HTX initiation.
-
Decoy site publishes
ticketPub(X25519, 32B),ticketKeyID(8B), and a carrier policy describing allowed carriers and probabilities:BN-Ticket: v1; carriers=cookie:0.5,query:0.3,body:0.2; len=24..64 -
Client generates
cliPriv/cliPub(X25519) and 32-Bnonce32. -
sharedSecret = X25519(cliPriv, ticketPub). -
hour = floor(unixTime/3600)(UTC). -
salt = SHA256("betanet-ticket-v1" ‖ ticketKeyID ‖ uint64_be(hour)). -
accessTicket = HKDF(sharedSecret, salt, "", 32). -
Client sends exactly one carrier chosen per policy with variable-length padding to match
len:- Cookie (recommended):
Cookie: <site-name>=Base64URL( 0x01 ‖ cliPub32 ‖ ticketKeyID8 ‖ nonce32 ‖ accessTicket32 ‖ pad )A__Host-prefix is RECOMMENDED. - Query parameter:
...?bn1=<Base64URL(payload)> - Body (POST) with
Content-Type: application/x-www-form-urlencodedcontainingbn1=<Base64URL(payload)>.
- Cookie (recommended):
-
Server verification:
- recompute for
hour ∈ {now-1, now, now+1}, - reject duplicates for tuple
(cliPub, hour)within 2 h, - enforce per-/24 IPv4 and /56 IPv6 token buckets.
- recompute for
-
Servers MUST parse fields in order (
version, cliPub32, ticketKeyID8, nonce32, accessTicket32) and MUST ignore trailing bytes (padding). Accepted padding range is 24..64 bytes. -
On duplicate rejection, clients SHOULD rotate
cliPub. -
On failure, server serves only decoy content.
-
Inner handshake MUST be Noise XK over the outer TLS tunnel.
-
From 2027-01-01, initiators MUST use hybrid (X25519-Kyber768); prior to that, X25519 is RECOMMENDED.
-
Derive
K0 = HKDF-Expand-Label(TLS-Exporter, "htx inner v1", "", 64).- Split per direction:
K0c,K0s. - Derive per-direction nonce salt
NS = HKDF(K0*, "ns", "", 12).
- Split per direction:
-
AEAD Nonce:
nonce = NS XOR (LE64(counter) ‖ LE32(0)); counter starts at 0 and increments per frame. -
Rekeying (MUST meet all):
- Send
KEY_UPDATEwhen any: ≥ 8 GiB, ≥ 2¹⁶ frames, or ≥ 1 h since last (re)key per direction. - New keys:
K' = HKDF(K, "next", transcript_hash, 64); reset counter; deriveNS'.
- Send
-
Ordering: Receivers MUST accept
KEY_UPDATEout-of-order relative to data frames and MUST discard frames that verify only under the previous key after receiving and acknowledgingKEY_UPDATE. Senders MUST cease using the old key immediately after transmittingKEY_UPDATE.
struct Frame {
uint24 length; // ciphertext length (excl. tag)
uint8 type; // 0=STREAM, 1=PING, 2=CLOSE, 3=KEY_UPDATE, 4=WINDOW_UPDATE
varint stream_id; // present if type==STREAM or type==WINDOW_UPDATE
uint8[] ciphertext;
}- Client streams odd; server streams even.
- Flow-control window: 65 535; send
WINDOW_UPDATEwhen ≥ 50 % consumed.
- H2 SETTINGS MUST mirror origin within tolerances learned during pre-flight (§5.1).
- PING cadence MUST be random in [10 s, 60 s] with ±10 % jitter; periodicity is PROHIBITED.
- PRIORITY frames SHOULD follow the origin’s baseline rate; if unknown, send on [0.5 %, 3 %] of connections at random.
- Idle padding: if no DATA for [200 ms, 1 200 ms], send [0, 3 KiB] dummy encrypted DATA (uniform in both).
- Attempt QUIC v1 on UDP-443 with MASQUE
CONNECT-UDP. - On failure, retry TCP with randomized back-off [200 ms, 1 200 ms], fresh ClientHello randomness, no session resumption, and fresh QUIC CIDs when applicable.
- To defeat induced linkability, clients MUST launch cover connections to ≥ 2 unrelated origins (non-HTX) within [0, 1 000 ms] of the retry; HTX start MUST be delayed by an additional [100, 700 ms] chosen independently.
- Cover connections MUST NOT exceed 2 retries per minute and MUST be torn down within [3, 15] s unless they carry user traffic.
PeerID = multihash 0x12 0x20 || SHA-256(pubkey).
/betanet/htx/1.1.0 (TCP-443)
/betanet/htxquic/1.1.0 (QUIC-443)
/betanet/webrtc/1.0.0 (optional)
Clients MUST iterate methods a → e until ≥ 5 peers respond:
| Order | Method | Central infra? |
|---|---|---|
| a | Rotating Rendezvous DHT: 64 ephemeral IDs SHA256("bn-seed" ‖ BeaconSet(epochDay) ‖ i) |
No |
| b | mDNS service _betanet._udp |
No |
| c | Bluetooth LE UUID 0xB7A7 |
No |
| d | Onion v3 list (signed, mirrored via IPFS) | Minimal |
| e | DNS fallback list | Yes (fallback) |
- Deterministic seeds from 1.0 are REMOVED.
- Responders MUST require proof-of-work (initial ≥ 22 bits, adaptive per §6.5) and rate-limit per source prefix; verification MUST be constant-time.
- Epoch definition:
epochDay = floor(unixTime/86 400)in UTC.
- CID =
multihash(SHA-256(content)). - Bitswap-v2 on
/betanet/bitswap/2.2.0. - Requesters SHOULD open ≥ 2 parallel streams on distinct SCION paths and MAY open a third under good conditions.
- Each bootstrap responder MUST maintain sliding-window metrics and adjust PoW difficulty to keep accept rate at the 95th percentile of capacity.
- Rate-limits MUST apply per
/24IPv4,/56IPv6, and per-AS aggregates; any bucket MUST NOT exceed 5 % of responder capacity.
| Mode | Requirement |
|---|---|
| strict | Every stream through ≥ 3 Nym hops |
| balanced (default) | ≥ 2 hops until peer-trust ≥ 0.8 |
| performance | No mixnet unless destination label .mixreq |
epoch = floor(unixTime/3600).BeaconSet(epoch) = XOR32(drand(epoch), nistRBv2(epoch), ethL1_finalized_hash(epoch)), each a 32-byte value; components MAY be substituted by governance.- If all components are unavailable, use fallback
BeaconSet(epoch) = SHA256("bn-fallback" ‖ K0c ‖ uint64_be(epoch))and MUST log the condition. - For each stream, initiator picks 16-B
streamNonce. seed = SHA256( BeaconSet(epoch) ‖ srcPeerID ‖ dstPeerID ‖ streamNonce ).- Hops chosen by VRF over
seedfrom the advertised mixnode set. - Diversity: within
(src,dst,epoch), avoid reusing the exact hop set until ≥ 8 distinct sets are tried. - Topology: include at least one hop outside both source and destination AS groups.
Computed from:
- uptime attestations signed by ≥ 8 distinct AS groups over a 30-day window,
- observed relay behaviour,
- staked ecash capped by per-AS limits (L7 §10.2). Thresholds are normative; combination is implementation-defined.
betanet://<hex SHA-256(service-pubkey)>[/resource]
Verify that the peer’s presented pubkey hashes to the ID.
A record is valid iff an identical payload hash appears finalized on at least 2 of 3 chains, each with native finality:
- Handshake L1: ≥ 12 confirmations and not reorged for ≥ 1 h.
- Filecoin FVM: chain reports finalized.
- Ethereum L2 “Raven-Names”: block marked finalized by the rollup.
Record payload (UTF-8):
betanet1 pk=<hex32> seq=<u64> sig=<base64sig> exp=<unixSec>
seqMUST increase monotonically perpk.- Conflicts: higher
seqwins once finality condition is met.
Liveness rule. If fewer than 2 chains provide finality for ≥ 14 days, nodes MAY accept an Emergency Advance for a pk when all hold:
- A quorum certificate with ≥ 67 % of effective governance weight (§10.2–§10.3) over the payload hash (
pk,seq,sig,exp). - The certificate is anchored once on any available chain (best-effort).
- When 2-of-3 finality resumes, the first finalized record at ≥ seq supersedes emergency records.
Quorum certificate format (CBOR map).
{ payloadHash, epoch, signers[], weights[], sigs[] }
Each sig is Ed25519 over ("bn-aa1" ‖ payloadHash ‖ epoch). Verifiers MUST validate weights per §10.2–§10.3 and reject duplicates or lower-epoch certificates.
- Each mint = FROST-Ed25519 (n ≥ 5, t = 3) group.
- Keyset ID =
SHA-256(sorted pubkeys). - Mints announce on
betanet.mintswith ≥ 22-bit PoW and an HTX contact endpoint.
Voucher (128 B):
keysetID32 ‖ secret32 ‖ aggregatedSig64
aggregatedSig64is the 64-B Ed25519 aggregate signature oversecret32.- Relays MUST accept vouchers only for known keysets; unknown keysets MAY be cached pending validation.
- Per-keyset and per-peer rate-limits MUST apply.
Relays MAY redeem ≥ 10 000 sat via their own Lightning node or swap with peers. Vouchers MUST NOT leave encrypted streams.
score = log2(1 + seconds_uptime / 86_400) // capped at 16
vote_weight_raw = uptime_score + log10(total_ecash_staked / 1_000 sat + 1)
- Per-AS cap: the sum of
vote_weight_rawacross all nodes within the same L1 AS MUST be capped to 20 % of the global total. - Per-Org cap: nodes mapped to the same RPKI organisation (or equivalent attestation) MUST be capped to 25 % combined.
- Effective weight:
vote_weight = min(vote_weight_raw, caps).
A proposal passes when all hold:
Σ weight(ACK) ≥ 0.67 × Σ weight(active_nodes_14d), whereactive_nodes_14dare nodes seen on HTX within 14 days.- ACKs span ≥ 24 distinct AS groups and ≥ 3 SCION ISDs; no single AS contributes > 20 % nor single Org > 25 % of ACK weight.
- ACKs are observed over ≥ 2 disjoint path classes per §4 with consistent reachability (median loss < 2 %).
- A partition check confirms the median path diversity and ACK composition did not degrade by > 20 % in the 7 days prior to close.
After threshold, activation waits ≥ 30 days. If §10.3 fails at any time ≥ 7 days before activation, activation MUST be deferred until criteria are met for 7 consecutive days. Raven Development Team publishes a time-lock hash of the final text.
An implementation is compliant if it:
- Implements HTX over TCP-443 and QUIC-443 with origin-mirrored TLS + ECH; performs per-connection calibration (§5.1).
- Uses negotiated-carrier, replay-bound access tickets (§5.2) with variable lengths and rate-limits.
- Performs inner Noise XK with key separation, nonce lifecycle, and rekeying (§5.3); uses hybrid X25519-Kyber768 from 2027-01-01.
- Emulates HTTP/2/3 with adaptive cadences and origin-mirrored parameters (§5.5).
- Bridges non-SCION links by HTX-tunnelled transition; no on-wire transition header on public networks (§4.2).
- Offers
/betanet/htx/1.1.0and/betanet/htxquic/1.1.0transports (§6.2). - Bootstraps via rotating rendezvous IDs derived from BeaconSet with PoW and multi-bucket rate-limits; deterministic seeds not used (§6.3–§6.5).
- Selects mixnodes using BeaconSet randomness with per-stream entropy and path diversity (§7.2); “balanced” mode enforces ≥ 2 hops until trust ≥ 0.8 (§7.1–§7.3).
- Verifies alias ledger with finality-bound 2-of-3 and applies Emergency Advance liveness only under §8.2 conditions; validates quorum certificates as specified.
- Accepts 128-B Cashu vouchers for known keysets with PoW adverts and rate-limits; supports Lightning settlement (§9).
- Enforces anti-concentration caps, diversity, and partition checks for governance (§10).
- Implements anti-correlation fallback with cover connections on UDP→TCP retries (§5.6).
- Builds are reproducible and publish SLSA 3 provenance artifacts for release binaries.
- 1.1 peers MAY offer
/betanet/htx/1.0.0ALPN for legacy interop. - Legacy on-wire transition headers MUST NOT be used on public networks; bridge via HTX tunnels.
- 64-B vouchers MAY be issued only to legacy peers; 1.1 receivers MUST accept both for the operator-defined deprecation window.