commit f2d62fa03d6a71ea162ae6c9615a5d5a9040c8ca Author: anthonyrawlins Date: Mon Mar 23 20:49:44 2026 +1100 Initial workspace: scaffold + constitution + spec documents Rust workspace with 5 crates (mesh-types, mesh-crypto, mesh-network, mesh-validator, mesh-wallet), PROJECT_CONSTITUTION.md for CHORUS automated ingestion, and the full MESH protocol specification suite. Co-Authored-By: Claude Opus 4.6 diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..b615ee1 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,19 @@ +[target.x86_64-unknown-linux-gnu] +linker = "clang" +rustflags = ["-C", "link-arg=-fuse-ld=mold"] + +[build] +# jobs defaults to number of CPUs + +[profile.dev] +opt-level = 0 +debug = true + +[profile.test] +opt-level = 1 # crypto tests too slow at opt-level 0 + +[profile.release] +opt-level = 3 +lto = "thin" +codegen-units = 1 +strip = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..97f8e81 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/target +Cargo.lock +*.swp +*.swo +.DS_Store diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..1b5186f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[workspace] +resolver = "2" +members = [ + "crates/mesh-types", + "crates/mesh-crypto", + "crates/mesh-network", + "crates/mesh-validator", + "crates/mesh-wallet", +] + +[workspace.package] +version = "0.1.0" +edition = "2024" +license = "Apache-2.0" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8607605 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + Copyright 2026 MESH Protocol Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PROJECT_CONSTITUTION.md b/PROJECT_CONSTITUTION.md new file mode 100644 index 0000000..add35f9 --- /dev/null +++ b/PROJECT_CONSTITUTION.md @@ -0,0 +1,414 @@ +# Project: MESH + +**Repository:** https://gitea.reset.org/tony/mesh (TBC) +**Language:** Rust (edition 2024, toolchain 1.85.0) +**License:** Apache 2.0 +**Created:** 2026-03-23 +**Status:** Constitution Phase + +## Overview + +MESH (Minimal-Exchange Settlement Hypergraph) is a decentralised payment +protocol that settles retail transactions in under 300ms using Byzantine +Consistent Broadcast — without a blockchain, without a native token, and +with confidential amounts via Pedersen commitments and Bulletproofs+ +range proofs. This constitution covers the **Tier 1 MVP**: a 4-validator +local testnet with a CLI wallet that can send and receive confidential +payments. + +## Constraints + +- **Single model:** All agents run the same LLM backend. No role-to-model + mapping is available. +- **MVP scope only:** Tier 1 (consensusless settlement) only. No Tier 2 + DAG-BFT, no Tier 3 aBFT, no multi-currency routing, no connectors, + no stealth addresses. These are specified but deferred. +- **No external network:** Agents work against a local Gitea repo. No + public APIs, no npm/PyPI fetches during agent sessions. +- **Deterministic serialisation:** No serde. All encode/decode is + hand-written per SPEC-002 §2.8. This is a hard constraint from the + spec — agents must not introduce serde-based serialisation. +- **Constant-time crypto:** All secret-dependent operations must use + constant-time implementations. Agents must use the dalek crate family, + not roll their own. +- **Pinned dependencies:** Exact crate versions are specified in the Dev + Environment Specification. Agents must not upgrade or substitute crates + without a gate approval. + +## Councils + +### Council: types +**Scope:** Core data structures and deterministic binary serialisation (SPEC-002) +**Agents:** 2 builders, 1 reviewer +**File area:** crates/mesh-types/** +**Depends on:** none +**Spec refs:** SPEC-002 §2.2–2.8 (primitive types, AccountState, Transition, Recipient, SettlementCertificate, ValidatorVote, EquivocationProof, Value Semiring, serialisation rules) + +#### Task: Define primitive types and enums +Implement all primitive types from SPEC-002 §2.2: u8, u32, u64, u128, +Hash (32-byte SHA3-256 output), PublicKey (32-byte Ed25519), Signature +(64-byte Ed25519), Commitment (32-byte compressed Edwards point), +AssetID (32-byte hash). Define enums: TransitionType (Send, Receive, +Exchange, OnRamp, OffRamp), NodeType (Validator, Client, Connector). +**File area:** crates/mesh-types/src/primitives.rs +- [ ] All types defined with correct byte sizes +- [ ] `AssetID` computed as `SHA3-256(asset_name || issuer_pubkey || precision)` +- [ ] No floating-point types anywhere in the crate + +#### Task: Implement AccountState and Transition structures +Define `AccountState` (owner, sequence, balances map, state_hash, +last_cert, created_at) and `Transition` (version, type, sender, +sequence, recipients, asset_id, amount, range_proof, fee, fee_proof, +causal_deps, expiry, memo, signature) per SPEC-002 §2.3–2.4. +**File area:** crates/mesh-types/src/structures.rs +- [ ] `AccountState` struct with `Map` for balances +- [ ] `Transition` struct with all 14 fields from SPEC-002 §2.4.1 +- [ ] `Recipient` struct (address, amount commitment, range_proof) +- [ ] `SettlementCertificate` struct (transition_hash, epoch, votes) +- [ ] `ValidatorVote` struct (validator_id, signature) +- [ ] `EquivocationProof` struct (two conflicting transitions + votes) + +#### Task: Deterministic binary serialisation +Hand-write encode/decode functions for every type. Rules per SPEC-002 +§2.8: little-endian integers, length-prefixed Vec, presence-flag +optionals, declaration-order struct fields, sorted-key maps. No serde. +**File area:** crates/mesh-types/src/codec.rs +- [ ] `encode()` and `decode()` for every struct +- [ ] Round-trip property tests (encode then decode = identity) for every type +- [ ] Canonical form: identical data always produces identical bytes +- [ ] Malformed input returns errors, never panics + +#### Task: Value Semiring implementation +Implement the Value Semiring from SPEC-002 §2.7: aggregation (⊕) for +same-asset addition, exchange (⊗) for currency conversion with +floor-division and remainder per Security Addendum AV-005. All +arithmetic in u128, no floating point. +**File area:** crates/mesh-types/src/value.rs +- [ ] `⊕` aggregation for same-AssetID values +- [ ] `⊗` exchange with floor division, remainder returned to sender +- [ ] Overflow checked: `ERR_OVERFLOW` on u128 overflow in multiplication +- [ ] ValueSet type for multi-asset aggregation + +### Council: crypto +**Scope:** Cryptographic operations — keys, signatures, commitments, range proofs (SPEC-006, SPEC-007) +**Agents:** 2 builders, 1 reviewer +**File area:** crates/mesh-crypto/** +**Depends on:** types +**Spec refs:** SPEC-006 §6.4.1 (key derivation), SPEC-007 §7.2–7.3 (Pedersen commitments, Bulletproofs+), Security Addendum AV-002 (fee range proofs), AV-007 (ephemeral key handling) + +#### Task: Key generation and domain-separated hashing +Ed25519 key pair generation via `ed25519-dalek`. Derive view key per +SPEC-006 §6.4.1. Domain-separated SHA3-256 hashing (each usage context +gets a unique prefix to prevent cross-domain collisions). +**File area:** crates/mesh-crypto/src/keys.rs +- [ ] `generate_keypair()` from CSPRNG +- [ ] `derive_view_key()` per SPEC-006 §6.4.1 +- [ ] Domain-separated hash function with context tags +- [ ] All secret keys implement `Zeroize` on drop + +#### Task: Pedersen commitments +Implement `Commit(value, blinding) = value·G + blinding·H` using +`curve25519-dalek` Ristretto operations. Generator H from +nothing-up-my-sleeve construction per SPEC-007 §7.2. Homomorphic +verification: `Σ(C_recipient_i) + C_fee = C_amount`. +**File area:** crates/mesh-crypto/src/pedersen.rs +- [ ] `commit(value, blinding)` returns Commitment +- [ ] Generator H derived from hash-to-point (nothing-up-my-sleeve) +- [ ] `verify_conservation(inputs, outputs)` using point arithmetic +- [ ] Blinding factor addition/subtraction for balance updates + +#### Task: Bulletproofs+ range proofs +Generate and verify range proofs for values in [0, 2^64) using `dalek +bulletproofs` with Merlin transcripts. Proofs must bind to transaction +hash per SPEC-007 §7.3.2. Fee commitments MUST have range proofs per +Security Addendum AV-002. +**File area:** crates/mesh-crypto/src/rangeproof.rs +- [ ] `prove_range(value, blinding, transcript)` returns RangeProof +- [ ] `verify_range(commitment, proof, transcript)` returns bool +- [ ] Proof bound to transaction hash via Merlin transcript +- [ ] Zero-value commitments produce valid range proofs +- [ ] Negative/overflow values produce proofs that fail verification + +#### Task: Transaction construction and validation +Build complete `Transition` with committed amounts and range proofs. +Implement all 9 validation rules from SPEC-002 §2.4.3 with Security +Addendum amendments (AV-002 fee range proofs, AV-003 causal dependency +relevance check). +**File area:** crates/mesh-crypto/src/validation.rs +- [ ] `build_transition()` constructs a fully signed Transition +- [ ] All 9 validation rules implemented in order +- [ ] Each rule returns the specified error code on failure +- [ ] AV-002: fee range proof required (including zero-fee) +- [ ] AV-003: causal deps checked for existence AND relevance +- [ ] Test vectors for each validation rule (valid + each failure mode) + +**Gate:** Cryptographic implementation review — verify Pedersen generator +derivation, Bulletproofs+ transcript binding, and constant-time +properties before downstream councils consume mesh-crypto. + +### Council: network +**Scope:** QUIC transport layer, message framing, handshake protocol (SPEC-009) +**Agents:** 2 builders, 1 reviewer +**File area:** crates/mesh-network/** +**Depends on:** types +**Spec refs:** SPEC-009 §9.2–9.5, §9.8–9.9 (QUIC transport, framing, handshake, stream multiplexing, rate limiting, keepalive) + +#### Task: QUIC server and client +QUIC transport using `quinn` with TLS 1.3 via `rustls`. Self-signed +certificates for testnet. Server accepts connections on configurable +address. Client connects with ALPN identifier "mesh/0". +**File area:** crates/mesh-network/src/transport.rs +- [ ] QUIC server binds and accepts connections +- [ ] QUIC client connects with ALPN "mesh/0" +- [ ] TLS 1.3 with self-signed certs (via `rcgen`) +- [ ] Connection errors handled gracefully (no panics) + +#### Task: Message framing and dispatch +Length-prefixed message framing: `[length: u32][type: u8][payload]` per +SPEC-009 §9.4. Maximum frame size 4MB. Message type dispatch to +handlers. Implement all message type IDs from SPEC-009 §9.4.1 (MVP +subset: 0x01–0x04, 0x40–0x42, 0xF0–0xF1, 0xFF). +**File area:** crates/mesh-network/src/framing.rs +- [ ] Encode/decode framed messages +- [ ] Reject frames exceeding 4MB +- [ ] Dispatch by message type to handler callbacks +- [ ] Malformed frames rejected (tested with fuzzy input) + +#### Task: Handshake protocol +MESH HandshakeMessage exchange per SPEC-009 §9.3: protocol version, +cipher suites, node type, public key, epoch, signature proof of key +ownership. Verify remote node's identity. +**File area:** crates/mesh-network/src/handshake.rs +- [ ] HandshakeMessage struct with all fields from SPEC-009 §9.3.2 +- [ ] Signature verification of remote node's public key +- [ ] Validator nodes checked against current epoch's validator set +- [ ] Connection closed on any handshake failure + +#### Task: Stream multiplexing and keepalive +Dedicated QUIC streams per message category per SPEC-009 §9.5: streams +0–3 for handshake/keepalive, 4–7 for Tier 1, 20–23 for queries. +PING/PONG keepalive every 30s per SPEC-009 §9.9. +**File area:** crates/mesh-network/src/streams.rs +- [ ] Stream ID ranges assigned per SPEC-009 §9.5 +- [ ] PING sent every 30s if no other traffic +- [ ] PONG response within 5s +- [ ] Connection closed after 3 missed PINGs + +### Council: validator +**Scope:** Validator node binary — state store, vote handling, equivocation detection, certificate processing (SPEC-003) +**Agents:** 3 builders, 1 reviewer +**File area:** crates/mesh-validator/** +**Depends on:** types, crypto, network +**Spec refs:** SPEC-003 §3.3 (vote/certificate protocol), SPEC-002 §2.4.3 (validation rules), Security Addendum AV-003 (causal deps), AV-004 (sharding), AV-006 (epoch boundary) + +#### Task: Account state store +Embedded key-value store using `sled` for AccountState keyed by +PublicKey. CRUD operations. Certificate store keyed by transition hash. +Equivocation record store keyed by (sender, sequence). +**File area:** crates/mesh-validator/src/store.rs +- [ ] `get_account(pubkey)` returns Option +- [ ] `put_account(pubkey, state)` persists atomically +- [ ] `get_certificate(hash)` for causal dependency lookups +- [ ] `put_equivocation(sender, seq, proof)` for detection records + +#### Task: VOTE_REQUEST handler +Receive a Transition, run all 9 validation rules from SPEC-002 §2.4.3 +(with Security Addendum amendments). If valid, sign a vote per SPEC-003 +§3.3.1. If invalid, return VOTE_REJECT with error code. Record +(sender, sequence, hash) for equivocation detection. +**File area:** crates/mesh-validator/src/vote.rs +- [ ] All 9 validation rules applied in order +- [ ] Vote signature: `Sign(validator_key, transition_hash || epoch)` +- [ ] VOTE_RESPONSE sent on success, VOTE_REJECT on failure +- [ ] Equivocation lock: reject second transition for same (sender, seq) + +#### Task: Equivocation detection and proof +Maintain map of `(sender, sequence) → transition_hash`. On conflict, +produce EquivocationProof containing both conflicting transitions and +their votes. Broadcast proof to all connected validators. +**File area:** crates/mesh-validator/src/equivocation.rs +- [ ] Detect conflicting transitions for same (sender, sequence) +- [ ] Produce EquivocationProof with both transitions +- [ ] Broadcast proof to peers +- [ ] Reject both transitions once equivocation detected + +#### Task: SETTLEMENT_CERTIFICATE handler +Receive a certificate. Verify ≥ 2f+1 valid votes from current epoch's +validator set (with one-epoch grace period per Security Addendum +AV-006). Apply state transition: debit sender, credit recipients. +Store certificate. +**File area:** crates/mesh-validator/src/certificate.rs +- [ ] Verify vote count ≥ 2f+1 +- [ ] Verify all vote signatures against correct epoch's validator set +- [ ] AV-006: accept current epoch and epoch-1, reject epoch-2 and future +- [ ] Apply state transition atomically (debit + credit + sequence bump) +- [ ] Store certificate in permanent record + +#### Task: Account query handler and validator config +Respond to QUERY_ACCOUNT with current account state. TOML configuration +file for validator: listen address, peer addresses, validator set +(public keys), epoch number, shard assignment. +**File area:** crates/mesh-validator/src/query.rs, crates/mesh-validator/src/config.rs +- [ ] QUERY_ACCOUNT returns current AccountState +- [ ] TOML config loaded at startup +- [ ] Validator key loaded from file (generated on first run) + +### Council: wallet +**Scope:** CLI wallet binary — key management, payment flow, balance tracking (SPEC-003 client side) +**Agents:** 2 builders, 1 reviewer +**File area:** crates/mesh-wallet/** +**Depends on:** types, crypto, network +**Spec refs:** SPEC-003 §3.3 (client-side protocol), SPEC-007 §7.2 (balance decryption via blinding factors), MVP Roadmap §Milestone 4 + +#### Task: Key management +`mesh-wallet keygen` generates Ed25519 key pair + derives view key. +Saves to encrypted file. `mesh-wallet show-address` prints public key. +Blinding factor store (sled DB keyed by transaction hash) — this is +the wallet's most sensitive data. +**File area:** crates/mesh-wallet/src/keys.rs +- [ ] `keygen` command generates and saves key pair +- [ ] `show-address` prints public key in hex +- [ ] Blinding factors stored locally per transaction +- [ ] Secret keys zeroized on drop + +#### Task: Send payment flow +`mesh-wallet send --to --amount --asset `. +Constructs a Transition with Pedersen-committed amount and Bulletproofs+ +range proof. Broadcasts VOTE_REQUEST to all configured validators. +Collects 2f+1 votes. Assembles SettlementCertificate. Broadcasts +certificate. Prints certificate hash. +**File area:** crates/mesh-wallet/src/send.rs +- [ ] Constructs valid Transition with committed amounts +- [ ] Sends VOTE_REQUEST to all validators +- [ ] Collects 2f+1 votes (tolerates slow/failed validators) +- [ ] Assembles and broadcasts SettlementCertificate +- [ ] Stores blinding factors for sent transaction + +#### Task: Receive and balance commands +`mesh-wallet receive --cert ` submits a Receive transition +referencing the certificate. `mesh-wallet balance` queries a validator +and decrypts committed balance using stored blinding factors. +`mesh-wallet history` lists all settlements with certificate hashes. +**File area:** crates/mesh-wallet/src/receive.rs, crates/mesh-wallet/src/balance.rs +- [ ] `receive` command submits Receive transition with causal dep +- [ ] `balance` command queries validator, decrypts locally +- [ ] `history` lists sent and received settlements +- [ ] Handles case where blinding factors are missing (display "encrypted") + +### Council: testnet +**Scope:** 4-validator testnet orchestration, crash recovery, end-to-end integration (MVP Roadmap §Milestone 5) +**Agents:** 1 builder, 1 reviewer +**File area:** config/**, docker-compose.yml, Dockerfile, tests/integration/** +**Depends on:** validator, wallet +**Spec refs:** MVP Roadmap §Milestone 5, Dev Environment Specification §5 + +#### Task: Docker Compose testnet +docker-compose.yml starting 4 validators on a bridge network. +Per-validator TOML config. Shared volume for validator key distribution. +Genesis validator credits initial test accounts. +**File area:** docker-compose.yml, Dockerfile, config/** +- [ ] `docker compose up` starts 4 validators +- [ ] Each validator has unique config (listen addr, peers, keys) +- [ ] Genesis mechanism credits initial accounts with test tokens +- [ ] `docker compose down -v` cleanly wipes all state + +#### Task: End-to-end integration test +Automated test: Alice creates account, receives genesis credit, sends +500 tokens to Bob, Bob receives, both check balances. Confidential +amounts throughout — validators never see plaintext. Run as `cargo test` +in the workspace root. +**File area:** tests/integration/** +- [ ] Alice→Bob send/receive completes successfully +- [ ] Balances correct after transfer (Alice: 9500, Bob: 500) +- [ ] All amounts are Pedersen-committed (no plaintext in validator logs) +- [ ] Test passes against 4-validator docker testnet + +#### Task: Crash recovery test +Kill one validator. Verify system continues (3/4 = 2f+1). Restart +killed validator. It catches up by requesting missed certificates. +All 4 validators converge to identical state. +**File area:** tests/integration/** +- [ ] Transactions succeed with 3/4 validators +- [ ] Restarted validator syncs missed certificates +- [ ] All 4 validators have identical account state after sync + +### Council: infra +**Scope:** Project scaffolding, CI pipeline, build configuration, benchmarks (MVP Roadmap §Milestone 0, §Milestone 6) +**Agents:** 1 builder, 1 reviewer +**File area:** Cargo.toml, .cargo/**, .github/**, rust-toolchain.toml, benches/**, deny.toml +**Depends on:** none +**Spec refs:** Dev Environment Specification §2.3–2.4 (Rust toolchain, cargo config), §6 (CI pipeline), §7 (crate dependencies) + +#### Task: Workspace scaffolding +Cargo workspace with crates: mesh-types, mesh-crypto, mesh-network, +mesh-validator, mesh-wallet. Root Cargo.toml. rust-toolchain.toml +pinned to 1.85.0. .cargo/config.toml with mold linker. deny.toml for +license compliance (Apache 2.0 compatible only, no GPL). +**File area:** Cargo.toml, .cargo/config.toml, rust-toolchain.toml, deny.toml +- [ ] `cargo build` succeeds on empty workspace +- [ ] Rust 1.85.0 pinned via rust-toolchain.toml +- [ ] mold linker configured in .cargo/config.toml +- [ ] `cargo deny check licenses` passes + +#### Task: CI pipeline +GitHub Actions workflow: format check (rustfmt), lint (clippy -D +warnings), build all targets, test all targets, audit dependencies +(cargo-audit), license compliance (cargo-deny). Runs on push and PR. +**File area:** .github/workflows/ci.yml +- [ ] CI runs on every push and PR +- [ ] rustfmt, clippy, build, test, audit, deny all pass +- [ ] Uses `rust:1.85.0-bookworm` container image +- [ ] Cargo registry cached across runs + +#### Task: Benchmarks +Criterion benchmarks for: Bulletproofs+ prove/verify time, Ed25519 +sign/verify, Pedersen commit, serialisation round-trips, end-to-end +Tier 1 latency. +**File area:** benches/** +- [ ] `cargo bench` runs all benchmarks +- [ ] Range proof generation and verification benchmarked +- [ ] Signature operations benchmarked +- [ ] Results written to stdout in criterion format + +## Cross-Cutting Concerns + +**Coding standards:** +- `cargo fmt --all` enforced. Unformatted code is rejected by CI. +- `cargo clippy -- -D warnings` enforced. All warnings are errors. +- No `unsafe` code without a `// SAFETY:` comment explaining why. +- No `unwrap()` or `expect()` in library code. Use `Result` types. +- All public functions have doc comments. + +**Error handling:** +- Every validation failure returns the specific error code from SPEC-002 + §2.4.3 (ERR_UNSUPPORTED_VERSION, ERR_INVALID_SIGNATURE, etc.). +- Network errors are logged and retried with backoff, never panicked. + +**Security:** +- All secret key material uses `zeroize` crate for secure erasure. +- Constant-time operations for all secret-dependent code paths (use + `subtle` crate for comparisons where needed). +- No logging of secret keys, blinding factors, or plaintext amounts. +- Security Addendum amendments (AV-001 through AV-007) are mandatory + for all relevant code paths. + +**Testing:** +- Property-based tests via `proptest` for serialisation round-trips. +- Every validation rule has a positive test and a negative test. +- Integration tests run against the 4-validator docker testnet. + +## Acceptance Criteria + +The coordinator evaluates these as exit triggers via +`ov coordinator check-complete`: + +- [ ] All 5 crates compile with zero warnings (`cargo clippy -- -D warnings`) +- [ ] All unit tests pass (`cargo test --all-targets`) +- [ ] Serialisation round-trip property tests pass for every type +- [ ] Cryptographic test vectors pass (key gen, sign/verify, commit, range proof) +- [ ] 4-validator testnet starts via `docker compose up` +- [ ] End-to-end confidential payment: Alice sends 500 tokens to Bob through 4 validators, both balances correct +- [ ] Crash recovery: kill 1 validator, transact, restart, state converges +- [ ] Benchmarks run and produce results (range proof < 500ms, verify < 10ms target) +- [ ] `cargo audit` reports no known vulnerabilities +- [ ] `cargo deny check licenses` passes (Apache 2.0 compatible only) diff --git a/crates/mesh-crypto/Cargo.toml b/crates/mesh-crypto/Cargo.toml new file mode 100644 index 0000000..476bc11 --- /dev/null +++ b/crates/mesh-crypto/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "mesh-crypto" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "Cryptographic operations for MESH protocol — keys, signatures, commitments, range proofs" + +[dependencies] +mesh-types = { path = "../mesh-types" } diff --git a/crates/mesh-crypto/src/lib.rs b/crates/mesh-crypto/src/lib.rs new file mode 100644 index 0000000..14480b6 --- /dev/null +++ b/crates/mesh-crypto/src/lib.rs @@ -0,0 +1 @@ +// MESH Protocol — Cryptographic Primitives (SPEC-006, SPEC-007) diff --git a/crates/mesh-network/Cargo.toml b/crates/mesh-network/Cargo.toml new file mode 100644 index 0000000..85aa7d7 --- /dev/null +++ b/crates/mesh-network/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "mesh-network" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "QUIC transport layer, message framing, and peer protocol for MESH" + +[dependencies] +mesh-types = { path = "../mesh-types" } diff --git a/crates/mesh-network/src/lib.rs b/crates/mesh-network/src/lib.rs new file mode 100644 index 0000000..fe736fc --- /dev/null +++ b/crates/mesh-network/src/lib.rs @@ -0,0 +1 @@ +// MESH Protocol — Network Transport (SPEC-009) diff --git a/crates/mesh-types/Cargo.toml b/crates/mesh-types/Cargo.toml new file mode 100644 index 0000000..a1a4faa --- /dev/null +++ b/crates/mesh-types/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "mesh-types" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "Core data structures and deterministic binary serialisation for MESH protocol" diff --git a/crates/mesh-types/src/lib.rs b/crates/mesh-types/src/lib.rs new file mode 100644 index 0000000..7a1b592 --- /dev/null +++ b/crates/mesh-types/src/lib.rs @@ -0,0 +1 @@ +// MESH Protocol — Core Data Structures (SPEC-002) diff --git a/crates/mesh-validator/Cargo.toml b/crates/mesh-validator/Cargo.toml new file mode 100644 index 0000000..674fb26 --- /dev/null +++ b/crates/mesh-validator/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "mesh-validator" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "MESH validator node — state store, vote handling, certificate processing" + +[dependencies] +mesh-types = { path = "../mesh-types" } +mesh-crypto = { path = "../mesh-crypto" } +mesh-network = { path = "../mesh-network" } diff --git a/crates/mesh-validator/src/lib.rs b/crates/mesh-validator/src/lib.rs new file mode 100644 index 0000000..79bd973 --- /dev/null +++ b/crates/mesh-validator/src/lib.rs @@ -0,0 +1 @@ +// MESH Protocol — Validator Node (SPEC-003) diff --git a/crates/mesh-wallet/Cargo.toml b/crates/mesh-wallet/Cargo.toml new file mode 100644 index 0000000..db60181 --- /dev/null +++ b/crates/mesh-wallet/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "mesh-wallet" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "MESH CLI wallet — key management, confidential payments, balance tracking" + +[dependencies] +mesh-types = { path = "../mesh-types" } +mesh-crypto = { path = "../mesh-crypto" } +mesh-network = { path = "../mesh-network" } diff --git a/crates/mesh-wallet/src/lib.rs b/crates/mesh-wallet/src/lib.rs new file mode 100644 index 0000000..bbf1972 --- /dev/null +++ b/crates/mesh-wallet/src/lib.rs @@ -0,0 +1 @@ +// MESH Protocol — CLI Wallet (SPEC-003 client side) diff --git a/docs/specs/MESH-Dev-Environment-Specification.md b/docs/specs/MESH-Dev-Environment-Specification.md new file mode 100644 index 0000000..7bd8f5e --- /dev/null +++ b/docs/specs/MESH-Dev-Environment-Specification.md @@ -0,0 +1,1160 @@ +**MESH PROTOCOL** + +*Development Environment Specification* + +Toolchains, Images, and Setup for VM-Based Development + +Version 1.0 \| March 2026 + +**1. Overview** + +This document specifies the complete development environment for the +MESH protocol reference implementation. It is designed for a single +developer working in a virtual machine environment, using official +Docker images and standard package managers wherever possible. + +The environment is structured as a primary development VM running +Docker, with containerised toolchains for build, test, and formal +verification. This ensures reproducibility: any developer on any host OS +can recreate the identical environment from this document. + +**1.1 Host VM Requirements** + + ------------------- --------------------------------------------------- + **Requirement** **Specification** + + Operating System Ubuntu 24.04 LTS (Noble Numbat), server or desktop + edition. This is the reference OS. All commands in + this document assume Ubuntu 24.04. Other Linux + distributions will work but package names may + differ. + + Architecture x86_64 (amd64). ARM64 (aarch64) is supported but + some Docker images may require emulation. All + specified images have amd64 variants. + + CPU Minimum: 4 cores. Recommended: 8+ cores. Rust + compilation and TLA+ model checking are both + CPU-intensive. + + RAM Minimum: 8 GB. Recommended: 16 GB. The TLC model + checker is a JVM application and benefits from + large heap sizes. Rust's linker (mold/lld) also + benefits from available RAM. + + Disk Minimum: 50 GB free. Recommended: 100 GB. Rust's + target/ directory grows quickly. Docker images + consume 5--10 GB. The cargo registry cache uses + 1--5 GB. + + Network Internet access required for initial setup (pulling + images, crates). Subsequent development can be done + offline if all dependencies are vendored. + ------------------- --------------------------------------------------- + +**1.2 Environment Architecture** + +The development environment consists of three layers: + +- **Layer 1 --- Host VM:** Ubuntu 24.04 with Docker Engine, Git, and + an editor (VS Code or Neovim). This is where you write code and run + docker compose commands. + +- **Layer 2 --- Build Container:** Official Rust Docker image with + additional system dependencies. This is where Rust code compiles. + Mounted as a volume so source files live on the host. + +- **Layer 3 --- Auxiliary Containers:** TLA+ tools, Tamarin Prover, + and the multi-validator testnet. These run as separate Docker + containers orchestrated by docker compose. + +**2. Host VM Setup** + +**2.1 Base Packages** + +Install the following packages on the host VM. These are all available +from Ubuntu's default APT repositories. + +> sudo apt update && sudo apt upgrade -y +> +> sudo apt install -y \\ +> +> build-essential pkg-config libssl-dev \\ +> +> git curl wget ca-certificates \\ +> +> docker.io docker-compose-v2 \\ +> +> jq tmux htop \\ +> +> clang lld mold + + ------------------- --------------- ------------------------------------- + **Package** **Version** **Purpose** + + docker.io ≥24.0 Container runtime. Ubuntu's official + Docker package. Alternatively install + Docker CE from docker.com --- both + work. + + docker-compose-v2 ≥2.24 Multi-container orchestration for the + testnet and auxiliary tools. Uses the + docker compose (v2, no hyphen) + syntax. + + git ≥2.43 Version control. Standard. + + build-essential current GCC, make, libc headers. Needed for + some Rust crate build scripts that + compile C code. + + pkg-config current Helps Rust crates find system + libraries (e.g., OpenSSL headers). + + libssl-dev current OpenSSL development headers. Required + by the quinn QUIC library for TLS + 1.3. + + clang ≥17 Alternative C/C++ compiler. Some + crates prefer clang for + cross-compilation. + + lld ≥17 LLVM linker. Faster than GNU ld for + large Rust binaries. + + mold ≥2.4 Even faster linker than lld. + Recommended for development builds. + Set via .cargo/config.toml. + + jq current JSON processor. Useful for parsing + benchmark output and test vectors. + + tmux current Terminal multiplexer. You will want + multiple panes when running 4 + validators. + ------------------- --------------- ------------------------------------- + +**2.2 Docker Post-Install** + +Add your user to the docker group so you can run Docker without sudo: + +> sudo usermod -aG docker \$USER +> +> newgrp docker \# apply group change without logout +> +> docker run hello-world \# verify it works + +**2.3 Rust Toolchain (Host-Native)** + +While compilation happens inside Docker containers for reproducibility, +you will also want a native Rust installation on the host for IDE +integration (rust-analyzer), quick cargo check cycles, and running +individual tests without the container overhead. + +> curl \--proto \'=https\' \--tlsv1.2 -sSf https://sh.rustup.rs \| sh -s +> \-- -y \\ +> +> \--default-toolchain stable \\ +> +> \--profile default \\ +> +> \--component rust-analyzer clippy rustfmt +> +> source \"\$HOME/.cargo/env\" +> +> rustup \--version \# verify: rustup 1.28+ +> +> cargo \--version \# verify: cargo 1.85+ +> +> rustc \--version \# verify: rustc 1.85+ + +Pin the Rust version in the project root to ensure all developers and CI +use the same compiler: + +> \# In the project root, create rust-toolchain.toml: +> +> \[toolchain\] +> +> channel = \"1.85.0\" +> +> components = \[\"clippy\", \"rustfmt\", \"rust-analyzer\"\] +> +> targets = \[\"x86_64-unknown-linux-gnu\"\] + +**2.4 Cargo Configuration** + +Create .cargo/config.toml in the project root to set the fast linker and +compilation flags: + +> \# .cargo/config.toml +> +> \[target.x86_64-unknown-linux-gnu\] +> +> linker = \"clang\" +> +> rustflags = \[\"-C\", \"link-arg=-fuse-ld=mold\"\] +> +> \[build\] +> +> \# Use all available cores for compilation +> +> jobs = 0 +> +> \[profile.dev\] +> +> \# Speed up dev builds at the cost of optimisation +> +> opt-level = 0 +> +> debug = true +> +> \[profile.test\] +> +> opt-level = 1 \# Some crypto tests are too slow at opt-level 0 +> +> \[profile.release\] +> +> opt-level = 3 +> +> lto = \"thin\" +> +> codegen-units = 1 +> +> strip = true +> +> **WHY mold?:** The default GNU linker (ld) can take 5--15 seconds to +> link a medium-sized Rust binary. mold reduces this to under 1 second. +> Over hundreds of compile-test cycles per day, this saves hours of +> cumulative wait time. It is the single highest-impact developer +> experience improvement. + +**2.5 Editor / IDE** + +Either of the following is fully supported: + +- **VS Code + rust-analyzer extension:** Install via the Extensions + marketplace. rust-analyzer provides inline type hints, + go-to-definition, auto-completion, and integrated test running. Add + the Even Better TOML extension for Cargo.toml editing. + +- **Neovim + rust-analyzer via nvim-lspconfig:** If you prefer + terminal-based editing. Requires Neovim 0.9+ and the nvim-lspconfig + plugin configured for rust_analyzer. + +Whichever editor you choose, ensure it is configured to run rustfmt on +save. The project enforces formatting via CI --- unformatted code will +be rejected. + +**3. Docker Images** + +All containerised toolchains use official images from Docker Hub or +well-established community images. No custom base images. Every image is +pinned to a specific tag for reproducibility. + +**3.1 Image Registry** + + --------------------------------------- ------------------------- ------------------------- + **Image** **Tag (pinned)** **Purpose** + + docker.io/library/rust 1.85.0-bookworm Primary build image. + Debian Bookworm base with + full Rust toolchain. Used + for compiling all MESH + crates. \~1.4 GB. + + docker.io/library/rust 1.85.0-slim-bookworm Slim build variant. No + GCC, no man pages. Used + for CI builds where image + pull time matters. \~800 + MB. + + docker.io/library/debian bookworm-slim Runtime base image. For + the final validator and + wallet binaries. Minimal: + \~80 MB. + + docker.io/library/eclipse-temurin 21-jre-jammy Java 21 runtime for TLA+ + tools (TLC model checker, + SANY parser). Eclipse + Temurin is the official + successor to + AdoptOpenJDK. \~220 MB. + + ghcr.io/tamarin-prover/tamarin-prover 1.8.0 Tamarin Prover for + cryptographic protocol + verification. Official + GitHub Container Registry + image. + + docker.io/library/python 3.12-slim-bookworm Python runtime for test + vector generation + scripts, benchmarking + scripts, and the + Jupyter-based TLA+ + environment. \~150 MB. + + docker.io/jupyter/minimal-notebook latest Jupyter notebook + environment for + interactive TLA+ + specification development + using tlaplus-jupyter + kernel. \~1.2 GB. + --------------------------------------- ------------------------- ------------------------- + +**3.2 Pull All Images** + +Run the following to pre-fetch all images. This will consume +approximately 5 GB of disk space and takes 5--15 minutes depending on +bandwidth. + +> docker pull rust:1.85.0-bookworm +> +> docker pull rust:1.85.0-slim-bookworm +> +> docker pull debian:bookworm-slim +> +> docker pull eclipse-temurin:21-jre-jammy +> +> docker pull ghcr.io/tamarin-prover/tamarin-prover:1.8.0 +> +> docker pull python:3.12-slim-bookworm +> +> docker pull jupyter/minimal-notebook:latest + +**3.3 Build Container (Dockerfile.build)** + +This Dockerfile extends the official Rust image with the additional +system libraries and tools needed to compile MESH crates: + +> \# Dockerfile.build +> +> FROM rust:1.85.0-bookworm +> +> \# System dependencies for crypto crates and QUIC +> +> RUN apt-get update && apt-get install -y \--no-install-recommends \\ +> +> pkg-config libssl-dev clang lld mold \\ +> +> cmake \\ \# some crates need cmake +> +> && rm -rf /var/lib/apt/lists/\* +> +> \# Install additional Rust tools +> +> RUN rustup component add clippy rustfmt rust-analyzer +> +> RUN cargo install cargo-audit cargo-deny cargo-nextest +> +> \# cargo-nextest: faster test runner with better output +> +> \# cargo-audit: checks dependencies for known vulnerabilities +> +> \# cargo-deny: checks licenses and advisories +> +> WORKDIR /workspace +> +> VOLUME /workspace + +Build and tag it: + +> docker build -f Dockerfile.build -t mesh-build:latest . + +Usage --- compile the project inside the container with host source +mounted: + +> docker run \--rm -v \$(pwd):/workspace -v +> cargo-cache:/usr/local/cargo/registry \\ +> +> mesh-build:latest cargo build +> +> \# Run tests: +> +> docker run \--rm -v \$(pwd):/workspace -v +> cargo-cache:/usr/local/cargo/registry \\ +> +> mesh-build:latest cargo nextest run +> +> \# Run clippy: +> +> docker run \--rm -v \$(pwd):/workspace -v +> cargo-cache:/usr/local/cargo/registry \\ +> +> mesh-build:latest cargo clippy \-- -D warnings +> +> **CARGO CACHE VOLUME:** The -v cargo-cache:/usr/local/cargo/registry +> flag creates a named Docker volume that persists the cargo registry +> cache across container runs. Without this, every docker run would +> re-download all crates. The volume survives container restarts and +> typically grows to 1--3 GB. + +**3.4 Runtime Container (Dockerfile.runtime)** + +The runtime image is minimal. It contains only the compiled binary and +its runtime dependencies. This is what the testnet validators run. + +> \# Dockerfile.runtime +> +> FROM debian:bookworm-slim +> +> RUN apt-get update && apt-get install -y \--no-install-recommends \\ +> +> ca-certificates libssl3 \\ +> +> && rm -rf /var/lib/apt/lists/\* +> +> COPY \--from=builder /workspace/target/release/mesh-validator +> /usr/local/bin/ +> +> COPY \--from=builder /workspace/target/release/mesh-wallet +> /usr/local/bin/ +> +> EXPOSE 4430/udp \# QUIC port for validator +> +> EXPOSE 4431/udp \# QUIC port for client connections +> +> ENTRYPOINT \[\"mesh-validator\"\] + +This uses a multi-stage build. The full Dockerfile combines +Dockerfile.build and Dockerfile.runtime: + +> \# Dockerfile (multi-stage) +> +> FROM rust:1.85.0-bookworm AS builder +> +> RUN apt-get update && apt-get install -y \--no-install-recommends \\ +> +> pkg-config libssl-dev clang lld mold cmake \\ +> +> && rm -rf /var/lib/apt/lists/\* +> +> WORKDIR /workspace +> +> COPY . . +> +> RUN cargo build \--release +> +> FROM debian:bookworm-slim +> +> RUN apt-get update && apt-get install -y \--no-install-recommends \\ +> +> ca-certificates libssl3 && rm -rf /var/lib/apt/lists/\* +> +> COPY \--from=builder /workspace/target/release/mesh-validator +> /usr/local/bin/ +> +> COPY \--from=builder /workspace/target/release/mesh-wallet +> /usr/local/bin/ +> +> EXPOSE 4430/udp 4431/udp +> +> ENTRYPOINT \[\"mesh-validator\"\] + +**4. Formal Verification Toolchains** + +**4.1 TLA+ (TLC Model Checker)** + +TLA+ is used to formally verify the consensus protocol properties +(SPEC-010 §10.6). The TLC model checker is a Java application +distributed as a JAR file. + +**4.1.1 Setup via Docker** + +There is no single official TLA+ Docker image on Docker Hub. The +recommended approach is a lightweight custom image based on Eclipse +Temurin JRE: + +> \# Dockerfile.tlaplus +> +> FROM eclipse-temurin:21-jre-jammy +> +> \# Download TLA+ tools JAR from official GitHub releases +> +> ARG TLAPLUS_VERSION=1.8.0 +> +> RUN apt-get update && apt-get install -y \--no-install-recommends wget +> && \\ +> +> wget -q +> https://github.com/tlaplus/tlaplus/releases/download/v\${TLAPLUS_VERSION}/tla2tools.jar +> \\ +> +> -O /opt/tla2tools.jar && \\ +> +> apt-get remove -y wget && apt-get autoremove -y && \\ +> +> rm -rf /var/lib/apt/lists/\* +> +> WORKDIR /specs +> +> VOLUME /specs +> +> \# Convenience aliases as entrypoints +> +> \# Usage: docker run mesh-tlaplus tlc MySpec.tla +> +> ENTRYPOINT \[\"java\", \"-cp\", \"/opt/tla2tools.jar\"\] +> +> CMD \[\"tlc2.TLC\", \"-help\"\] + +Build and use: + +> docker build -f Dockerfile.tlaplus -t mesh-tlaplus:latest . +> +> \# Parse a spec: +> +> docker run \--rm -v \$(pwd)/specs:/specs mesh-tlaplus:latest \\ +> +> tla2sany.SANY /specs/Tier1.tla +> +> \# Run the model checker: +> +> docker run \--rm -v \$(pwd)/specs:/specs mesh-tlaplus:latest \\ +> +> tlc2.TLC /specs/Tier1.tla -workers auto +> +> \# Interactive REPL: +> +> docker run \--rm -it -v \$(pwd)/specs:/specs mesh-tlaplus:latest \\ +> +> tlc2.REPL + +**4.1.2 Jupyter + TLA+ (Interactive Development)** + +For iterative specification development, the tlaplus-jupyter kernel +allows writing and checking TLA+ inside Jupyter notebooks: + +> \# Dockerfile.tlaplus-jupyter +> +> FROM jupyter/minimal-notebook:latest +> +> USER root +> +> RUN apt-get update && apt-get install -y \--no-install-recommends \\ +> +> default-jre-headless && rm -rf /var/lib/apt/lists/\* +> +> USER \${NB_UID} +> +> RUN pip install \--no-cache-dir tlaplus-jupyter +> +> RUN python -m tlaplus_jupyter.install +> +> WORKDIR /home/jovyan/specs + +Run it: + +> docker build -f Dockerfile.tlaplus-jupyter -t +> mesh-tlaplus-jupyter:latest . +> +> docker run \--rm -p 8888:8888 -v \$(pwd)/specs:/home/jovyan/specs \\ +> +> mesh-tlaplus-jupyter:latest +> +> \# Open http://localhost:8888 and create a TLA+ notebook + +**4.2 Tamarin Prover** + +Tamarin Prover is used to verify cryptographic protocol properties +(SPEC-010 §10.6). It has an official Docker image on GitHub Container +Registry. + +> \# Pull the official image: +> +> docker pull ghcr.io/tamarin-prover/tamarin-prover:1.8.0 +> +> \# Run a proof: +> +> docker run \--rm -v \$(pwd)/proofs:/proofs \\ +> +> ghcr.io/tamarin-prover/tamarin-prover:1.8.0 \\ +> +> tamarin-prover \--prove /proofs/PTLC_Atomicity.spthy +> +> \# Interactive mode (launches web UI on port 3001): +> +> docker run \--rm -p 3001:3001 -v \$(pwd)/proofs:/proofs \\ +> +> ghcr.io/tamarin-prover/tamarin-prover:1.8.0 \\ +> +> tamarin-prover interactive /proofs/ \--interface=\'\*4\' +> +> \# Open http://localhost:3001 for the Tamarin web interface +> +> **TAMARIN LEARNING CURVE:** Tamarin's specification language (spthy) +> has a steep learning curve. Start with the official tutorial at +> https://tamarin-prover.com/manual/master/book/ before attempting to +> model MESH protocols. Budget 2--4 weeks of study before writing +> production-quality proofs. + +**5. Testnet Orchestration** + +The full 4-validator testnet is orchestrated by docker compose. This is +the primary way to run the MVP end-to-end. + +**5.1 docker-compose.yml** + +> \# docker-compose.yml +> +> version: \"3.9\" +> +> services: +> +> validator-1: +> +> build: . +> +> container_name: mesh-validator-1 +> +> command: \[\"mesh-validator\", \"\--config\", +> \"/config/validator-1.toml\"\] +> +> volumes: +> +> \- ./config:/config:ro +> +> \- validator-1-data:/data +> +> ports: +> +> \- \"4430:4430/udp\" +> +> \- \"4431:4431/udp\" +> +> networks: +> +> \- meshnet +> +> validator-2: +> +> build: . +> +> container_name: mesh-validator-2 +> +> command: \[\"mesh-validator\", \"\--config\", +> \"/config/validator-2.toml\"\] +> +> volumes: +> +> \- ./config:/config:ro +> +> \- validator-2-data:/data +> +> ports: +> +> \- \"4432:4430/udp\" +> +> \- \"4433:4431/udp\" +> +> networks: +> +> \- meshnet +> +> validator-3: +> +> build: . +> +> container_name: mesh-validator-3 +> +> command: \[\"mesh-validator\", \"\--config\", +> \"/config/validator-3.toml\"\] +> +> volumes: +> +> \- ./config:/config:ro +> +> \- validator-3-data:/data +> +> ports: +> +> \- \"4434:4430/udp\" +> +> \- \"4435:4431/udp\" +> +> networks: +> +> \- meshnet +> +> validator-4: +> +> build: . +> +> container_name: mesh-validator-4 +> +> command: \[\"mesh-validator\", \"\--config\", +> \"/config/validator-4.toml\"\] +> +> volumes: +> +> \- ./config:/config:ro +> +> \- validator-4-data:/data +> +> ports: +> +> \- \"4436:4430/udp\" +> +> \- \"4437:4431/udp\" +> +> networks: +> +> \- meshnet +> +> volumes: +> +> validator-1-data: +> +> validator-2-data: +> +> validator-3-data: +> +> validator-4-data: +> +> networks: +> +> meshnet: +> +> driver: bridge + +**5.2 Usage** + +> \# Build and start the testnet: +> +> docker compose up \--build -d +> +> \# View logs from all validators: +> +> docker compose logs -f +> +> \# View logs from one validator: +> +> docker compose logs -f validator-1 +> +> \# Run the wallet CLI against the testnet: +> +> docker compose exec validator-1 mesh-wallet \--config +> /config/wallet.toml \\ +> +> send \--to \ \--amount 500 \--asset test-token +> +> \# Stop the testnet: +> +> docker compose down +> +> \# Stop and wipe all data (clean slate): +> +> docker compose down -v +> +> \# Simulate a crash: kill one validator +> +> docker compose stop validator-3 +> +> \# \... run transactions, they should still succeed (3/4 = 2f+1 with +> f=1) +> +> docker compose start validator-3 \# it should sync back up + +**6. CI/CD Pipeline** + +The project uses GitHub Actions for continuous integration. The pipeline +runs on every push to any branch and every pull request to main. + +**6.1 GitHub Actions Workflow** + +> \# .github/workflows/ci.yml +> +> name: CI +> +> on: \[push, pull_request\] +> +> env: +> +> CARGO_TERM_COLOR: always +> +> RUST_BACKTRACE: 1 +> +> jobs: +> +> check: +> +> runs-on: ubuntu-24.04 +> +> container: rust:1.85.0-bookworm +> +> steps: +> +> \- uses: actions/checkout@v4 +> +> \- uses: actions/cache@v4 +> +> with: +> +> path: \| +> +> \~/.cargo/registry +> +> target/ +> +> key: \${{ runner.os }}-cargo-\${{ hashFiles(\'\*\*/Cargo.lock\') }} +> +> \- run: cargo fmt \--all \-- \--check +> +> \- run: cargo clippy \--all-targets \-- -D warnings +> +> \- run: cargo build \--all-targets +> +> \- run: cargo test \--all-targets +> +> audit: +> +> runs-on: ubuntu-24.04 +> +> container: rust:1.85.0-bookworm +> +> steps: +> +> \- uses: actions/checkout@v4 +> +> \- run: cargo install cargo-audit cargo-deny +> +> \- run: cargo audit +> +> \- run: cargo deny check licenses + +The pipeline enforces: formatting (rustfmt), lint warnings (clippy with +-D warnings), compilation, all tests pass, no known vulnerabilities +(cargo audit), and license compliance (cargo deny). Any failure blocks +merge. + +**7. Rust Crate Dependencies (Pinned)** + +These are the exact crate versions to be specified in Cargo.toml. All +versions are pinned and locked via Cargo.lock. Do not use version ranges +(e.g., \"\^1.0\") for cryptographic dependencies --- pin to the exact +patch version. + +**7.1 mesh-crypto** + + ---------------------- ------------- ------------------------------------- + **Crate** **Version** **Purpose and Notes** + + ed25519-dalek 2.1.1 Ed25519 signatures. Enable features: + \[\"hazmat\", \"rand_core\"\]. This + is the dalek-cryptography crate + maintained by the community since the + original author's departure. + + curve25519-dalek 4.1.3 Ristretto group operations for + Pedersen commitments. Enable + features: \[\"alloc\", + \"precomputed-tables\"\]. + + bulletproofs 4.0.0 Bulletproofs range proofs over + Ristretto. Depends on + curve25519-dalek and merlin. MIT + licensed. + + merlin 3.0.0 Transcript-based Fiat-Shamir + transform. Used by bulletproofs for + non-interactive proofs. + + sha3 0.10.8 SHA3-256 and SHAKE256. RustCrypto + project. Pure Rust. + + chacha20poly1305 0.10.1 ChaCha20-Poly1305 AEAD. For memo + encryption and transport-layer + encryption. + + rand 0.8.5 Cryptographically secure random + number generation. Uses OS entropy. + + rand_core 0.6.4 Core traits for RNG. Required by + dalek crates. + + zeroize 1.8.1 Securely zeroes memory on drop. MUST + be used for all secret key material. + ---------------------- ------------- ------------------------------------- + +**7.2 mesh-network** + + ---------------------- ------------- ------------------------------------- + **Crate** **Version** **Purpose and Notes** + + quinn 0.11.6 QUIC protocol implementation. Built + on tokio and rustls. This is the + primary networking dependency. + + rustls 0.23.22 TLS 1.3 implementation in Rust. No + OpenSSL dependency at runtime. Used + by quinn. + + rustls-pemfile 2.2.0 PEM file parsing for TLS + certificates. + + rcgen 0.13.2 X.509 certificate generation. Used to + create self-signed TLS certs for + testnet validators. + + tokio 1.43.0 Async runtime. Enable features: + \[\"full\"\]. All async I/O runs on + tokio. + + bytes 1.9.0 Efficient byte buffer manipulation. + Used for message framing. + ---------------------- ------------- ------------------------------------- + +**7.3 mesh-validator** + + ---------------------- ------------- ------------------------------------- + **Crate** **Version** **Purpose and Notes** + + sled 0.34.7 Embedded key-value database. Used for + account state, certificates, and + equivocation records. Note: sled is + in maintenance mode; if it becomes + unmaintained, migrate to redb + (0.22.0) as a drop-in replacement. + + toml 0.8.20 TOML configuration file parsing. For + validator config files. + + tracing 0.1.41 Structured logging framework. All log + output uses tracing macros. + + tracing-subscriber 0.3.19 Log output formatting. Enable + features: \[\"env-filter\", + \"json\"\]. JSON output for + machine-parseable logs. + ---------------------- ------------- ------------------------------------- + +**7.4 mesh-wallet** + + ---------------------- ------------- ------------------------------------- + **Crate** **Version** **Purpose and Notes** + + clap 4.5.26 Command-line argument parser. Enable + features: \[\"derive\"\]. All CLI + commands defined via derive macros. + + dialoguer 0.11.0 Interactive terminal prompts. Used + for key generation confirmation and + passphrase entry. + + hex 0.4.3 Hex encoding/decoding. For displaying + public keys and transaction hashes to + the user. + ---------------------- ------------- ------------------------------------- + +**7.5 Development and Testing** + + ---------------------- ------------- ------------------------------------- + **Crate** **Version** **Purpose and Notes** + + proptest 1.6.0 Property-based testing framework. + Used for serialisation round-trip + tests and fuzzing protocol + invariants. + + criterion 0.5.1 Benchmarking framework. Used for + crypto operation benchmarks (range + proof generation/verification, + signing, etc.). + + tokio-test 0.4.4 Utilities for testing async code. + Pairs with tokio. + + tempfile 3.14.0 Temporary file/directory creation for + test isolation. + ---------------------- ------------- ------------------------------------- + +> **DEPENDENCY HYGIENE:** Run cargo deny check licenses before adding +> any new dependency. MESH is Apache 2.0 licensed. All dependencies MUST +> be compatible (Apache 2.0, MIT, BSD-2, BSD-3, ISC, or Zlib). GPL +> dependencies are PROHIBITED because they would require the entire +> project to be GPL. LGPL dependencies are acceptable only if +> dynamically linked. + +**8. Repository Structure** + +The repository follows Rust workspace conventions with additional +top-level directories for specifications, formal proofs, and +configuration. + +> mesh/ +> +> ├── Cargo.toml \# Workspace root +> +> ├── Cargo.lock \# Pinned dependency versions +> +> ├── rust-toolchain.toml \# Pinned Rust version +> +> ├── .cargo/config.toml \# Build settings (linker, flags) +> +> ├── .github/workflows/ci.yml \# CI pipeline +> +> ├── Dockerfile \# Multi-stage build +> +> ├── Dockerfile.build \# Development build container +> +> ├── Dockerfile.tlaplus \# TLA+ tools container +> +> ├── Dockerfile.tlaplus-jupyter \# Interactive TLA+ notebooks +> +> ├── docker-compose.yml \# 4-validator testnet +> +> ├── deny.toml \# cargo-deny license config +> +> ├── LICENSE \# Apache 2.0 +> +> ├── README.md +> +> ├── FUTURE.md \# Ideas deferred from MVP scope +> +> │ +> +> ├── crates/ +> +> │ ├── mesh-types/ \# Data structures and serialisation +> +> │ │ ├── src/lib.rs +> +> │ │ └── Cargo.toml +> +> │ ├── mesh-crypto/ \# Cryptographic operations +> +> │ │ ├── src/lib.rs +> +> │ │ └── Cargo.toml +> +> │ ├── mesh-network/ \# QUIC transport layer +> +> │ │ ├── src/lib.rs +> +> │ │ └── Cargo.toml +> +> │ ├── mesh-validator/ \# Validator binary +> +> │ │ ├── src/main.rs +> +> │ │ └── Cargo.toml +> +> │ └── mesh-wallet/ \# CLI wallet binary +> +> │ ├── src/main.rs +> +> │ └── Cargo.toml +> +> │ +> +> ├── specs/ \# Formal specifications (TLA+) +> +> │ ├── Tier1.tla +> +> │ ├── Tier1.cfg \# TLC model config +> +> │ └── ValueSemiring.tla +> +> │ +> +> ├── proofs/ \# Tamarin protocol proofs +> +> │ ├── PTLC_Atomicity.spthy +> +> │ └── Stealth_Unlinkability.spthy +> +> │ +> +> ├── config/ \# Testnet configuration files +> +> │ ├── validator-1.toml +> +> │ ├── validator-2.toml +> +> │ ├── validator-3.toml +> +> │ ├── validator-4.toml +> +> │ └── wallet.toml +> +> │ +> +> ├── test-vectors/ \# Reference test vectors (JSON) +> +> │ ├── spec-002/ +> +> │ ├── spec-003/ +> +> │ └── spec-006/ +> +> │ +> +> ├── docs/ \# Specification documents (docx/pdf) +> +> │ ├── MESH-Protocol-Specification-Suite-v0.1.0.docx +> +> │ ├── MESH-Specification-Addendum-SPEC-004-005-009.docx +> +> │ ├── MESH-MVP-Roadmap-Solo-Bootstrap.docx +> +> │ └── MESH-Dev-Environment.docx +> +> │ +> +> └── benches/ \# Criterion benchmarks +> +> ├── crypto_bench.rs +> +> └── serialisation_bench.rs + +**9. Quick Reference Card** + +Cut this page out and stick it on your monitor. + + --------------------------- --------------------------------------------- + **Task** **Command** + + Build (host) cargo build + + Build (container) docker run \--rm -v \$(pwd):/workspace -v + cargo-cache:/usr/local/cargo/registry + mesh-build:latest cargo build + + Test (fast) cargo nextest run + + Test (container) docker run \--rm -v \$(pwd):/workspace -v + cargo-cache:/usr/local/cargo/registry + mesh-build:latest cargo nextest run + + Lint cargo clippy \-- -D warnings + + Format cargo fmt \--all + + Format check cargo fmt \--all \-- \--check + + Audit deps cargo audit + + License check cargo deny check licenses + + Start testnet docker compose up \--build -d + + View testnet logs docker compose logs -f + + Stop testnet docker compose down + + Wipe testnet data docker compose down -v + + Kill one validator docker compose stop validator-3 + + Run TLC model check docker run \--rm -v \$(pwd)/specs:/specs + mesh-tlaplus:latest tlc2.TLC /specs/Tier1.tla + -workers auto + + Run Tamarin proof docker run \--rm -v \$(pwd)/proofs:/proofs + ghcr.io/tamarin-prover/tamarin-prover:1.8.0 + tamarin-prover \--prove + /proofs/PTLC_Atomicity.spthy + + Benchmark crypto cargo bench \--bench crypto_bench + + Generate release binary cargo build \--release + --------------------------- --------------------------------------------- diff --git a/docs/specs/MESH-MVP-Roadmap-Solo-Bootstrap.md b/docs/specs/MESH-MVP-Roadmap-Solo-Bootstrap.md new file mode 100644 index 0000000..faf07e4 --- /dev/null +++ b/docs/specs/MESH-MVP-Roadmap-Solo-Bootstrap.md @@ -0,0 +1,622 @@ +**MESH PROTOCOL** + +*MVP Roadmap* + +From Specification to Working Tier 1 Testnet + +Solo Bootstrap Edition + +Budget: \$0 \| Team: 1 person \| Timeline: 6--9 months evenings/weekends + +March 2026 + +**1. The Uncomfortable Truth About Solo Bootstrapping** + +The specification suite describes a complete protocol with 10 +specifications, three consensus tiers, a privacy layer, multi-hop +routing, and formal verification. Building all of that is a multi-year, +multi-million-dollar engineering effort. You are one person in Ballarat +working evenings and weekends. + +The entire strategy for the next 6--9 months is therefore about one +thing: proving the core thesis works with the minimum possible code, so +that the project becomes credible enough to attract contributors and +funding. Everything else is deferred. + +**The core thesis:** Byzantine Consistent Broadcast can settle everyday +retail payments in under 300ms, without a blockchain, without a native +token, and with confidential amounts. If you can demonstrate this --- +two wallets transacting through validators with Pedersen-committed +amounts and Bulletproofs+ range proofs --- you have something no one +else has built. + +**1.1 What the MVP IS** + +- **Tier 1 only.** No Tier 2 DAG-BFT, no Tier 3 aBFT. Those are + complex and not needed to prove the thesis. + +- **Single asset type.** No multi-currency routing, no connectors, no + exchange. Transfers in a single test token. + +- **Confidential amounts.** Pedersen commitments and Bulletproofs+ + from day one. This is the privacy differentiator --- without it, + you're just another FastPay clone. + +- **4 validators on a local testnet.** Running on your own machines or + cheap VPS instances. No public network. + +- **A command-line wallet.** No mobile app, no GUI. A CLI tool that + can create accounts, send payments, and verify receipts. + +- **Honest crash-only fault tolerance.** The MVP validators can crash + and recover. Full Byzantine fault tolerance is implemented in the + protocol logic, but adversarial testing comes later. + +**1.2 What the MVP is NOT** + +- Not a mobile app. Not a web wallet. Not a consumer product. + +- Not multi-currency. Not connected to real money. Not connected to + anything external. + +- Not formally verified. The TLA+ and Tamarin work comes after the MVP + proves the architecture. + +- Not audited. No security firm review. This is a testnet with test + tokens. + +- Not horizontally scaled. Single-shard validators. Scaling comes when + there's something worth scaling. + +- Not post-quantum. Suite 0 (Ed25519) only. PQ cipher suites are + specified but not implemented. + +**2. Technology Stack Decisions** + +Every choice here optimises for solo-developer velocity and correctness, +not for theoretical perfection. + + ----------------- ------------------ ------------------------------------ + **Component** **Choice** **Rationale** + + Language Rust Memory safety without GC. The entire + crypto ecosystem (dalek, curve25519, + bulletproofs) is Rust-native. The + spec mandates constant-time crypto, + and Rust's type system helps enforce + this. You'll need to learn it if you + haven't, but it's the right + long-term bet. + + Async runtime Tokio De facto standard for async Rust. + All networking, timers, and I/O + through Tokio. Single dependency for + the entire async layer. + + Networking quinn (QUIC) Rust QUIC implementation built on + Tokio. The spec mandates QUIC + (SPEC-009). Quinn is mature, + well-maintained, and handles TLS 1.3 + via rustls. + + Crypto: ed25519-dalek Mature, audited, constant-time + signatures Ed25519. Used by Signal, Solana, and + dozens of other projects. + + Crypto: curve25519-dalek Ristretto group operations for + commitments Pedersen commitments. Same library + family as ed25519-dalek. + Well-tested. + + Crypto: range bulletproofs The dalek-cryptography Bulletproofs + proofs (dalek) implementation. Uses Merlin + transcripts for Fiat-Shamir. + MIT-licensed. This is the same + codebase Monero evaluated. + + Crypto: hashing sha3 crate NIST SHA3-256 and SHAKE256. Pure + Rust, no C dependencies. + + Crypto: symmetric chacha20poly1305 ChaCha20-Poly1305 AEAD. RustCrypto + crate project. For memo encryption. + + Serialisation Custom binary (no The spec mandates deterministic + serde) byte-level encoding. Serde's binary + formats (bincode, etc.) do not + guarantee this across versions. + Write encode/decode by hand for all + protocol structures. It's tedious + but essential for interoperability. + + Storage sled (embedded DB) Embedded key-value store. No + external database dependency. Stores + account states, certificates, and + equivocation records. Can be + replaced later with RocksDB if + performance demands it. + + Build/CI cargo + GitHub Standard Rust toolchain. CI runs + Actions tests, clippy, and cargo-audit on + every push. + ----------------- ------------------ ------------------------------------ + +> **DELIBERATE OMISSIONS:** No web framework. No REST API. No gRPC. No +> GraphQL. The MVP wallet talks directly to validators over QUIC. Adding +> an HTTP API is a week of work later if needed. Don't build it now. + +**3. Milestone Plan** + +Each milestone is a shippable unit: it compiles, it passes tests, and it +does something demonstrable. Milestones are sequential --- each depends +on the previous one. Estimated hours assume 10--15 hours/week of focused +coding time. + +**Milestone 0: Project Skeleton (Week 1--2, \~20 hours)** + +*Deliverable:* A Rust workspace with crate structure, CI pipeline, and +all dependencies pinned. + +Set up the mono-repo workspace with these crates: + +- mesh-types --- All data structures from SPEC-002. Transition, + AccountState, SettlementCertificate, etc. Pure data, no logic. 100% + test coverage of serialisation round-trips. + +- mesh-crypto --- Thin wrapper around dalek crates. Key generation, + signing, verification, Pedersen commit, Bulletproofs+ prove/verify. + Domain-separated hashing per SPEC-006. + +- mesh-validator --- Validator node binary. Empty for now. + +- mesh-wallet --- CLI wallet binary. Empty for now. + +- mesh-network --- QUIC transport layer. Empty for now. + +This milestone is pure scaffolding. Write no protocol logic. Get the +types compiling, get serialisation working, get CI green. This is the +foundation everything else builds on. Do not skip it. + +> **DEFINITION OF DONE:** cargo build succeeds. cargo test passes. +> GitHub Actions CI is green. All SPEC-002 data structures are defined +> with encode/decode functions. Round-trip property tests (encode then +> decode) pass for every type. + +**Milestone 1: Cryptographic Core (Week 3--5, \~40 hours)** + +*Deliverable:* A standalone library that can create Pedersen-committed +transactions with Bulletproofs+ range proofs, and verify them. + +Implement in mesh-crypto: + +1. **Key generation:** Generate Ed25519 key pair + derive view key per + SPEC-006 §6.4.1. + +2. **Pedersen commitment:** Commit(value, blinding) = value·G + + blinding·H. Generate H from the nothing-up-my-sleeve construction + per SPEC-007 §7.2. + +3. **Range proof:** Generate and verify Bulletproofs+ proofs for values + in \[0, 2⁶⁴). Use dalek Bulletproofs with Merlin transcripts. Bind + to transaction hash per SPEC-007 §7.3.2. + +4. **Balance verification:** Given input commitments and output + commitments, verify that the sum of inputs equals the sum of outputs + (homomorphic check). + +5. **Transaction construction:** Build a complete Transition struct per + SPEC-002 §2.4.1 with committed amounts and range proofs. Sign with + sender's key. + +6. **Transaction validation:** Implement all 9 validation rules from + SPEC-002 §2.4.3. Every rule, in order, with the specified error + codes. + +Write test vectors for each operation. These become the reference test +suite that any future implementation must pass. + +> **DEFINITION OF DONE:** Can programmatically: create an account, +> construct a 500-unit confidential transfer with range proof, verify +> the transfer, confirm the balance check passes. Can also construct and +> detect an invalid transfer (negative value, insufficient balance, +> wrong signature) for each of the 9 validation rules. +> +> **THIS IS THE HARDEST MILESTONE:** Getting Bulletproofs+ integrated +> correctly with custom Pedersen generators and domain-separated +> transcripts is the single most technically demanding part of the MVP. +> Budget extra time. Read the dalek documentation twice. Write a +> throwaway prototype first if needed. + +**Milestone 2: Network Layer (Week 6--8, \~35 hours)** + +*Deliverable:* Two nodes can establish a QUIC connection, perform the +MESH handshake, and exchange protocol messages. + +Implement in mesh-network: + +7. QUIC server and client using quinn. TLS 1.3 with self-signed + certificates for testnet. + +8. Message framing: \[length: u32\]\[type: u8\]\[payload\] per SPEC-009 + §9.4. + +9. HandshakeMessage exchange per SPEC-009 §9.3. Verify identity key + signature. + +10. Stream multiplexing: separate QUIC streams for Tier 1 messages vs. + control messages. + +11. PING/PONG keepalive per SPEC-009 §9.9. + +12. Message dispatch: receive a framed message, deserialise, route to + handler by type. + +For the MVP, skip peer discovery (SPEC-009 §9.6). Validators are +configured with a static list of peer addresses. This is fine for a +4-node testnet. + +> **DEFINITION OF DONE:** Start two nodes. They connect over QUIC, +> exchange handshakes, verify identities. One sends a PING, the other +> responds with PONG. Message framing is correct (test with malformed +> frames to verify rejection). Logs show the full handshake sequence. + +**Milestone 3: Validator Core (Week 9--13, \~50 hours)** + +*Deliverable:* A validator node that can receive Tier 1 vote requests, +validate transitions, and return signed votes. + +Implement in mesh-validator: + +13. **Account state store:** sled database holding AccountState per + public key. CRUD operations. + +14. **Validator key management:** Load signing key from file. For MVP, + generate during first run and save. + +15. **VOTE_REQUEST handler:** Receive a Transition from a client. Run + all 9 validation rules. If valid, sign a vote (SPEC-003 §3.3.1 step + 2). Return VOTE_RESPONSE. If invalid, return VOTE_REJECT with error + code. + +16. **Equivocation detection:** Maintain a map of (sender, sequence) → + transition_hash. On any conflict, produce EquivocationProof and + reject. + +17. **SETTLEMENT_CERTIFICATE handler:** Receive a certificate. Verify ≥ + 2f+1 valid votes. Apply state transition: debit sender, credit + recipients. Store certificate. + +18. **Account query handler:** Respond to QUERY_ACCOUNT with current + account state (balance commitment, sequence number). + +This is the heart of the system. Take your time. Write exhaustive tests. +Every edge case in the validation rules needs a test. + +> **DEFINITION OF DONE:** Start a validator. Submit a valid transition +> via the network layer. Receive a signed vote. Submit an invalid +> transition (bad signature). Receive a rejection with the correct error +> code. Submit two conflicting transitions. Receive an equivocation +> proof. + +**Milestone 4: CLI Wallet (Week 14--17, \~40 hours)** + +*Deliverable:* A command-line wallet that can create accounts, send +confidential payments, and verify receipts. + +Implement in mesh-wallet: + +19. **Key management:** mesh-wallet keygen → generates key pair, saves + to file. mesh-wallet show-address → prints public key. + +20. **Send payment:** mesh-wallet send \--to \ \--amount + \ \--asset \. Constructs a Transition with + Pedersen-committed amount and Bulletproofs+ range proof. Broadcasts + to all configured validators. Collects 2f+1 votes. Assembles + certificate. Broadcasts certificate. Prints certificate hash. + +21. **Check balance:** mesh-wallet balance. Queries a validator for + current account state. Locally decrypts the committed balance using + stored blinding factors. + +22. **Receive:** mesh-wallet receive \--cert \. Submits a receive + transition referencing the certificate as a causal dependency. + +23. **Transaction history:** mesh-wallet history. Lists all sent and + received settlements with their certificate hashes. + +The wallet stores blinding factors locally (in a sled database keyed by +transaction hash). Without the blinding factors, the committed balance +is meaningless. This is the wallet's most sensitive data. + +> **DEFINITION OF DONE:** Alice creates an account. The genesis +> validator credits Alice's account with 10,000 test tokens (on-ramp via +> a hardcoded genesis transition). Alice sends 500 tokens to Bob. Bob +> receives them. Alice checks her balance: 9,500 (minus fee). Bob checks +> his balance: 500. Both balances are Pedersen-committed --- the +> validators never saw the plaintext amounts. + +**Milestone 5: Multi-Validator Testnet (Week 18--21, \~35 hours)** + +*Deliverable:* A 4-validator testnet where any validator can crash and +the system continues operating. + +This milestone takes the single-validator demo and makes it a real +distributed system: + +24. **Config file:** TOML configuration for validator: listen address, + peer addresses, validator set (public keys), epoch number. + +25. **Multi-validator vote collection:** Wallet connects to all 4 + validators, sends VOTE_REQUEST to all, collects 3 votes (2f+1 with + n=4, f=1), assembles certificate. + +26. **Certificate propagation:** Wallet broadcasts certificate to all + validators. All validators apply the state transition. State is + consistent across all 4. + +27. **Crash recovery:** Kill one validator. Verify the system still + works (wallet can collect 3/3 remaining votes). Restart the killed + validator. It catches up by requesting missed certificates from + peers. + +28. **Docker Compose:** A docker-compose.yml that starts 4 validators + and an initial wallet. One command to launch the entire testnet. + +> **DEFINITION OF DONE:** docker compose up starts 4 validators. Run the +> end-to-end send/receive flow. Kill one validator. Repeat the flow --- +> still works. Restart the killed validator. It syncs up. All 4 +> validators have identical account state. + +**Milestone 6: Benchmarks and Documentation (Week 22--24, \~25 hours)** + +*Deliverable:* Performance numbers, a README that explains what this is, +and a grant application package. + +29. **Latency benchmark:** Measure end-to-end time from wallet send to + certificate receipt. Run on 4 VPS instances (Sydney + Melbourne + + Perth + Brisbane or similar). Target: \<300ms. Document results. + +30. **Throughput benchmark:** Flood a single validator with vote + requests. Measure transactions per second. This establishes a + baseline. + +31. **Range proof benchmark:** Measure Bulletproofs+ prove and verify + time on a mid-range Android phone (or equivalent ARM device). + Target: prove \< 500ms, verify \< 10ms. + +32. **README.md:** What MESH is, what the MVP does, how to run it, + what's next. Clear, honest, no hype. + +33. **Grant application:** Prepare materials for NLnet Foundation, + Sovereign Tech Fund, and OTF FOSS Sustainability Fund. Include: + problem statement, demo video, benchmark results, specification + suite, budget request for next phase. + +> **DEFINITION OF DONE:** Published GitHub repo with working code, +> passing CI, benchmark results in the README, a 3-minute demo video of +> Alice paying Bob through 4 validators, and at least one grant +> application submitted. + +**4. Crate Dependency Map** + +The dependency structure ensures that each crate can be developed and +tested independently: + +mesh-wallet (binary) + +└─ mesh-network (QUIC transport) + +└─ mesh-crypto (signatures, commitments, proofs) + +└─ mesh-types (data structures, serialisation) + +mesh-validator (binary) + +└─ mesh-network + +└─ mesh-crypto + +└─ mesh-types + +└─ sled (embedded storage) + +mesh-network + +└─ quinn (QUIC) + +└─ rustls (TLS 1.3) + +└─ mesh-types + +mesh-crypto + +└─ ed25519-dalek + +└─ curve25519-dalek (Ristretto) + +└─ bulletproofs (dalek) + +└─ merlin (Fiat-Shamir transcripts) + +└─ sha3 + +└─ chacha20poly1305 + +└─ mesh-types + +mesh-types (zero external dependencies) + +**5. Risk Register** + +Honest accounting of what could go wrong and what to do about it. + + ------------------- --------------------------- ----------------------- + **Risk** **Impact** **Mitigation** + + Bulletproofs+ Delays Milestone 1 by 2--4 Start with the dalek + integration is weeks. This is the most bulletproofs example + harder than technically demanding part. code. Build a minimal + expected standalone test + (commit, prove, verify) + before integrating with + the full transaction + structure. If you're + stuck after 2 weeks, + pivot to plaintext + amounts for the MVP and + add confidentiality in + the next phase. + + Rust learning curve You know Python and JS. Spend week 0 (before + Rust's ownership model will Milestone 0) doing the + slow you down initially. first 12 chapters of + The Rust Programming + Language book. Write a + toy project. Don't try + to learn Rust while + building MESH. + + QUIC/quinn Quinn is powerful but has a Wrap quinn in a thin + complexity steep API. Connection abstraction layer early + management and error (mesh-network). All + handling are non-trivial. MESH code talks to your + abstraction, not to + quinn directly. If + quinn becomes painful, + you can swap it for + s2n-quic or fall back + to TCP+TLS for the + testnet. + + Motivation loss / Solo project, no external Set a public milestone. + burnout accountability, no revenue. Announce what you're + The most common cause of building on a relevant + open-source project death. forum (r/rust, a crypto + research mailing list, + or similar). External + accountability helps. + Ship Milestone 0 within + 2 weeks of starting --- + early momentum matters. + + Scope creep The spec has 10 documents. The milestones above + The temptation to "just add are the scope. If it's + Tier 2" or "just add not in a milestone, it + stealth addresses" is real. doesn't exist yet. + Write ideas down in a + FUTURE.md file and + close the mental loop. + + Someone builds this The uncertified DAG + Publish the + first confidential transaction specification suite + space is active. Another now. Establishing prior + project could announce art and an open + something similar. standard is more + valuable than a head + start in code. If + someone else builds a + compatible + implementation, that's + a success, not a + threat. + ------------------- --------------------------- ----------------------- + +**6. What Comes After the MVP** + +Once the Tier 1 testnet is working and grant applications are out, the +project enters Phase 1 (funded development). This is the Phase 1 roadmap +at headline level --- detailed specs already exist. + +**6.1 With Funding (\$50--100K AUD, 1--2 developers)** + +- **Tier 2 DAG-BFT consensus** (SPEC-004). This unlocks multi-party + settlements and atomic swaps. 3--4 months of work. + +- **Stealth addresses** (SPEC-007 §7.4). Recipient privacy. 2--3 + weeks. + +- **Multi-asset support** (SPEC-002 §2.7 Value Semiring). Multiple + asset types in the same testnet. 3--4 weeks. + +- **Basic connector** (SPEC-008). Single-hop value routing between two + asset types. 4--6 weeks. + +- **First security audit** (design review). \$200--300K AUD. This is + the single biggest expense and the single most important credibility + milestone. + +**6.2 With Serious Funding (\$250K+ AUD, 3--5 developers)** + +- **Tier 3 aBFT fallback** (SPEC-005). Complete consensus safety net. + +- **TLA+ formal verification** of Tier 1 safety properties. + +- **Hybrid post-quantum cipher suite** (Suite 1). Ed25519 + ML-DSA-65 + hybrid signatures. + +- **Mobile wallet SDK** (iOS/Android). This is what makes it real for + retail. + +- **Public testnet** with community-operated validators. + +- **Mainnet launch** with conservative parameters and permissioned + validator set. + +**6.3 Grant Targets** + + ------------------- ---------------- ------------------------------------- + **Fund** **Amount** **Fit** + + NLnet Foundation €5K--€50K Strong fit. NLnet funds open internet + (NGI) infrastructure. MESH's + payment-as-protocol narrative aligns + with their mission. Apply under NGI + Zero Entrust or NGI Zero Core. + + Sovereign Tech Fund €50K--€1M Good fit. STF funds open digital + infrastructure. The "replacement for + global payment rails" framing + resonates. Longer application + process. + + OTF FOSS Fund \$150K--\$400K Decent fit. OTF funds tools that + USD advance internet freedom. The + privacy-by-default angle is strong. + Requires US fiscal sponsor. + + Filecoin Foundation \$10K--\$100K Possible fit via their decentralised + (FFDW) USD web grants. Less obvious than the + above. + + GitHub Sponsors Variable Good for ongoing small contributions + once the project has visibility. + ------------------- ---------------- ------------------------------------- + +**7. Your Next 7 Days** + +Concrete actions to take this week, in order: + +34. **Publish the specification suite.** Create a public GitHub + repository. Upload the three spec documents (main suite + addendum + + this roadmap). Add an Apache 2.0 LICENSE file. Add a README that + says: "MESH is an open protocol specification for decentralised + payments. Reference implementation in progress." This establishes + the open standard and creates public accountability. + +35. **Register the domain.** mesh-protocol.org or similar. Park it with + a one-page site linking to the GitHub repo. Cost: \~\$15 AUD/year. + +36. **Set up the Rust workspace.** cargo new \--lib mesh-types, cargo + new \--lib mesh-crypto, cargo new \--bin mesh-validator, cargo new + \--bin mesh-wallet, cargo new \--lib mesh-network. Add a root + Cargo.toml workspace. Pin all dependency versions. Get CI green. + +37. **Write the first 5 structs.** AccountState, Transition, Recipient, + SettlementCertificate, ValidatorVote. With encode/decode. With + round-trip tests. Push to main. + +38. **Tell one person.** Not the internet. One person you trust and + respect. Show them the spec. Ask for honest feedback. External + perspective, this early, is invaluable. + +*The spec is the easy part. The code is where it becomes real. Start +this week.* diff --git a/docs/specs/MESH-Protocol-Specification-Suite-v0.1.0.md b/docs/specs/MESH-Protocol-Specification-Suite-v0.1.0.md new file mode 100644 index 0000000..616d240 --- /dev/null +++ b/docs/specs/MESH-Protocol-Specification-Suite-v0.1.0.md @@ -0,0 +1,1505 @@ +**MESH PROTOCOL** + +*Minimal-Exchange Settlement Hypergraph* + +Formal Protocol Specification Suite + +Version 0.1.0-draft + +March 2026 + +CLASSIFICATION: PUBLIC --- OPEN STANDARD + +License: Apache 2.0 (specification) / CC-BY-SA 4.0 (documentation) + +**Table of Contents** + +**SPEC-001: Overview, Conventions, and Threat Model** + +**1.1 Purpose** + +This document suite constitutes the formal specification of the MESH +protocol (Minimal-Exchange Settlement Hypergraph). It is intended to +provide sufficient detail for an independent engineering team to produce +a conformant implementation without access to the authors, the reference +implementation, or any other materials beyond these specifications and +the referenced academic papers. + +Each specification in this suite is self-contained for its component, +but cross-references other specifications where interfaces exist. +Implementers MUST read SPEC-001 before any other specification, as it +defines the conventions, terminology, and threat model that apply to all +subsequent documents. + +**1.2 Document Conventions** + +**RFC 2119 Keywords:** The key words MUST, MUST NOT, REQUIRED, SHALL, +SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in these +documents are to be interpreted as described in RFC 2119. All uses are +capitalised for emphasis. + +**Notation:** Mathematical notation follows standard conventions. Sets +are denoted by capital letters (A, E, V). Functions use lowercase (f, g, +σ). The symbol ≺ denotes the causal partial order. The symbol ‖ denotes +concatenation of byte strings. The symbol ⊕ denotes XOR. The notation +\[n\] means the set {0, 1, \..., n-1}. + +**Byte Encoding:** All multi-byte integers are encoded in little-endian +format unless explicitly stated otherwise. All cryptographic values +(public keys, signatures, hashes) are encoded as fixed-length byte +arrays. Lengths are specified in bytes. + +**Pseudo-code:** Algorithm descriptions use Python-like pseudo-code with +explicit type annotations. This is descriptive, not prescriptive --- +implementations may use any language or approach that produces identical +outputs for identical inputs across all test vectors. + +**1.3 Specification Suite Index** + + ----------- ----------------------------- ------------------------------ + **Spec ID** **Title** **Scope** + + SPEC-001 Overview, Conventions, and This document. Global + Threat Model conventions, terminology, + threat model, and security + properties. + + SPEC-002 Settlement Hypergraph Data Core data structures: + Model accounts, transitions, + hyperedges, causal ordering, + the Value Semiring. + + SPEC-003 Tier 1 --- Consensusless Byzantine Consistent Broadcast + Settlement Protocol for simple payments. Sub-300ms + finality path. + + SPEC-004 Tier 2 --- DAG-BFT Ordered DAG-based consensus for + Settlement complex multi-party + settlements requiring total + order. + + SPEC-005 Tier 3 --- Asynchronous BFT Liveness-guaranteed fallback + Fallback under network partition. aBFT + protocol. + + SPEC-006 Cryptographic Primitives and All cryptographic operations, + Cipher Suites key formats, cipher suite + negotiation, PQ migration. + + SPEC-007 Privacy Layer Pedersen commitments, + Bulletproofs+ range proofs, + stealth addresses, selective + disclosure. + + SPEC-008 Value Routing and Exchange Multi-hop routing, PTLC + atomicity, connector protocol, + packet format, price + discovery. + + SPEC-009 Network Transport and Peer Wire protocol, message + Discovery framing, peer discovery, + eclipse attack resistance. + + SPEC-010 Validator Operations and Validator lifecycle, key + Governance management, upgrade protocol, + fee model, governance. + ----------- ----------------------------- ------------------------------ + +**1.4 System Model** + +**1.4.1 Participants** + +The MESH network consists of the following participant types: + +- **Accounts:** End-user entities identified by a public key. An + account holds balances in zero or more asset types and initiates + settlements. An account has a monotonically increasing sequence + number that prevents replay attacks. Accounts do not run persistent + software --- they interact via client applications (wallets). + +- **Validators:** Infrastructure nodes that verify and certify state + transitions. The validator set V = {v₁, v₂, \..., vₙ} is known to + all participants and changes only through the governance protocol + (SPEC-010). Each validator holds a signing key pair. Validators are + expected to have persistent storage and reliable network + connectivity. + +- **Connectors:** Nodes that hold balances in multiple asset types and + facilitate cross-asset settlement by providing liquidity. Connectors + are a specialisation of accounts --- they are accounts that + additionally run the connector protocol (SPEC-008). Any account MAY + become a connector. + +**1.4.2 Threat Model** + +MESH assumes the following threat model, which applies to all +specifications: + +**Byzantine Validators:** Up to f \< n/3 validators may be Byzantine +(arbitrarily malicious). Byzantine validators may: crash, send +conflicting messages to different parties, collude with each other, +delay messages selectively, and attempt to forge or suppress +settlements. They may NOT break the cryptographic assumptions (see +SPEC-006). + +**Network Model:** The network is partially synchronous for Tier 1 and +Tier 2 protocols. This means there exists an unknown bound Δ such that +after Global Stabilisation Time (GST), all messages between correct +validators are delivered within Δ. Before GST, messages may be delayed +arbitrarily. For Tier 3, the network is fully asynchronous (no timing +assumptions). + +**Byzantine Accounts:** Any account may be Byzantine. A Byzantine +account may attempt to: double-spend (issue two conflicting transitions +from the same state), forge transaction certificates, or collude with +Byzantine validators. The protocol MUST prevent all such attacks when f +\< n/3. + +**Cryptographic Assumptions:** Security relies on: (a) the hardness of +the Discrete Logarithm Problem in the chosen elliptic curve group (Suite +0), (b) the hardness of Module-LWE (Suite 1+), (c) collision resistance +of SHA-3/SHAKE, (d) the random oracle model for Fiat-Shamir transforms. +These are specified precisely in SPEC-006. + +**1.4.3 Security Properties** + +The protocol MUST satisfy the following properties under the stated +threat model. These are the acceptance criteria for any conformant +implementation. + +> **SAFETY-1 (No Double-Spend):** If a settlement certificate is issued +> for a transition t on account a, then no conflicting transition t′ +> (same account, same sequence number, different content) can ever +> receive a valid settlement certificate. This holds even if f \< n/3 +> validators are Byzantine. +> +> **SAFETY-2 (Value Conservation):** For every settlement hyperedge e, +> the sum of all value debited from source accounts equals the sum of +> all value credited to destination accounts, within the same asset +> type. Cross-asset exchanges are modelled as paired settlements with an +> exchange rate, not as creation or destruction of value. +> +> **SAFETY-3 (No Inflation):** No state transition may increase the +> total supply of any asset type. The only way to introduce new value +> into the system is through the on-ramp protocol (SPEC-008 §8.6), which +> requires proof of external settlement. +> +> **LIVENESS-1 (Settlement Finality):** If a correct account initiates a +> valid Tier 1 settlement and at least 2f+1 validators are correct and +> reachable, the settlement achieves finality within 2Δ time (two +> message delays). +> +> **LIVENESS-2 (No Deadlock):** The protocol MUST NOT reach a state +> where a correct account's funds are permanently locked. All +> conditional settlements have timeouts. All escrows have expiration. No +> correct account can be denied access to its own balance indefinitely. +> +> **PRIVACY-1 (Amount Confidentiality):** Settlement amounts MUST NOT be +> observable by any party other than the sender, recipient, and (where +> applicable) the connectors on the settlement path. Validators verify +> amount validity through zero-knowledge proofs without learning the +> amounts. +> +> **PRIVACY-2 (Unlinkability):** Given two settlement certificates, no +> observer (including validators) can determine whether they involve the +> same sender or recipient, except with negligible probability, unless +> the sender or recipient voluntarily discloses this linkage. + +**1.5 Versioning and Compatibility** + +The MESH protocol uses semantic versioning (MAJOR.MINOR.PATCH). A change +in MAJOR version indicates a breaking change that requires all +validators to upgrade simultaneously (hard fork). A change in MINOR +version indicates a backward-compatible addition. A change in PATCH +version indicates a bug fix. + +All protocol messages include a version field. Validators MUST reject +messages with an unsupported MAJOR version. Validators SHOULD process +messages with a higher MINOR version than their own, ignoring unknown +fields. This enables rolling upgrades without network-wide coordination +for non-breaking changes. + +**SPEC-002: Settlement Hypergraph Data Model** + +**2.1 Purpose** + +This specification defines the core data structures of the MESH +protocol. All other specifications reference these structures. +Implementers MUST support all data types defined here with the exact +byte-level encoding specified. + +**2.2 Primitive Types** + + -------------- ---------- ----------------------------------------------- + **Type** **Size** **Description** + + u8 1 byte Unsigned 8-bit integer. + + u32 4 bytes Unsigned 32-bit integer, little-endian. + + u64 8 bytes Unsigned 64-bit integer, little-endian. + + u128 16 bytes Unsigned 128-bit integer, little-endian. Used + for all value amounts. Supports up to 3.4 × + 10³⁸ base units. + + Hash 32 bytes Output of SHA3-256. Used for content addressing + and Merkle commitments. + + PublicKey 32 bytes Ed25519 public key. For Suite 1+, see SPEC-006 + (Suite 0) for expanded sizes. + + Signature 64 bytes Ed25519 signature. For Suite 1+, see SPEC-006. + (Suite 0) + + Commitment 32 bytes Pedersen commitment point (compressed Edwards + form). See SPEC-007. + + RangeProof variable Bulletproofs+ range proof. See SPEC-007 for + encoding. + + AssetID 32 bytes SHA3-256(asset_name \|\| issuer_pubkey \|\| + precision). Uniquely identifies an asset type. + -------------- ---------- ----------------------------------------------- + +**2.3 Account State** + +An account is the fundamental unit of participation in the MESH network. +Each account is identified by its public key and maintains local state +that is updated by state transitions. + +**2.3.1 AccountState Structure** + +struct AccountState { + +owner: PublicKey, // The account's public key (identity) + +sequence: u64, // Monotonically increasing counter + +balances: Map\, // Balance per asset (committed) + +state_hash: Hash, // SHA3-256 of serialised state + +last_cert: Hash, // Hash of most recent settlement certificate + +created_at: u64, // Unix timestamp (seconds) of account creation + +} + +The sequence number starts at 0 for new accounts and increments by +exactly 1 for each transition. A validator MUST reject any transition +whose sequence number is not exactly last_sequence + 1. This is the +primary mechanism preventing double-spends: two conflicting transitions +would share the same sequence number, and the equivocation is +detectable. + +Balances are stored as Pedersen commitments, not plaintext values. A +commitment C = vG + bH commits to value v using blinding factor b. The +validator cannot learn v, but can verify that transitions are consistent +using the homomorphic property of the commitments (see SPEC-007). + +**2.3.2 Account Creation** + +An account is created by its first state transition. There is no +separate registration step. The first transition MUST have sequence +number 0 and MUST be a receive transition (receiving value from another +account or from the on-ramp protocol). An account with no balances and +no transitions does not exist in the protocol. + +**2.4 State Transitions** + +A state transition is an atomic change to one or more accounts. +Transitions are the edges of the causal graph. + +**2.4.1 Transition Structure** + +struct Transition { + +version: u8, // Protocol major version + +transition_type: TransitionType, // enum: Send, Receive, Exchange, +OnRamp, OffRamp + +sender: PublicKey, // Account initiating the transition + +sequence: u64, // Sender's next sequence number + +recipients: Vec\, // One or more recipients (hyperedge) + +asset_id: AssetID, // Asset being transferred + +amount: Commitment, // Value committed (Pedersen) + +range_proof: RangeProof, // Proves amount ≥ 0 and ≤ sender balance + +fee: Commitment, // Fee committed (paid to validators) + +fee_proof: RangeProof, // Proves fee ≥ 0 + +causal_deps: Vec\, // Hashes of transitions this depends on + +expiry: u64, // Unix timestamp after which transition is void + +memo: \[u8; 256\], // Encrypted end-to-end data (opaque to validators) + +signature: Signature, // Sender's signature over all above fields + +} + +**2.4.2 Recipient Structure** + +struct Recipient { + +address: PublicKey, // Recipient's public key (or stealth address) + +amount: Commitment, // Value committed to this recipient + +range_proof: RangeProof, // Proves amount ≥ 0 + +} + +A transition with multiple recipients is a single atomic operation. +Either all recipients receive their amounts, or none do. This is how +MESH natively supports multi-party settlements without requiring smart +contracts. + +**2.4.3 Transition Validation Rules** + +A validator MUST apply the following checks to every transition, in +order. If any check fails, the transition MUST be rejected with the +specified error code. + +1. **VERSION_CHECK:** transition.version MUST equal a supported + protocol major version. Error: ERR_UNSUPPORTED_VERSION. + +2. **SIGNATURE_CHECK:** The signature MUST be valid under the sender's + public key over the canonical serialisation of all fields except the + signature itself. Error: ERR_INVALID_SIGNATURE. + +3. **SEQUENCE_CHECK:** transition.sequence MUST equal the sender's + current sequence number + 1. Error: ERR_INVALID_SEQUENCE. + +4. **EXPIRY_CHECK:** The current time MUST be less than + transition.expiry. Error: ERR_EXPIRED. + +5. **BALANCE_CHECK:** The committed amount + fee MUST be provably ≤ the + sender's committed balance for the specified asset, using the + homomorphic property. Error: ERR_INSUFFICIENT_BALANCE. (Details in + SPEC-007.) + +6. **RANGE_CHECK:** All range proofs MUST verify. This proves all + amounts are non-negative and within the valid range \[0, 2⁶⁴). + Error: ERR_INVALID_RANGE_PROOF. + +7. **CONSERVATION_CHECK:** The sum of recipient amount commitments + + fee commitment MUST equal the sender's debited amount commitment. + Formally: Σ(recipient.amount) + fee = amount. This is checked on the + commitment points: Σ(C_recipient_i) + C_fee = C_amount. Error: + ERR_CONSERVATION_VIOLATION. + +8. **CAUSAL_CHECK:** Every hash in causal_deps MUST reference a + transition that the validator has already processed and certified. + Error: ERR_UNKNOWN_DEPENDENCY. + +9. **EQUIVOCATION_CHECK:** The validator MUST NOT have previously + signed a vote for a different transition with the same (sender, + sequence) pair. If it has, this is an equivocation attempt. The + validator MUST produce an equivocation proof (both conflicting + transitions) and broadcast it. Error: ERR_EQUIVOCATION. + +**2.5 Settlement Certificates** + +A settlement certificate is cryptographic proof that a transition has +been accepted by a quorum of validators and is therefore final. + +**2.5.1 Certificate Structure** + +struct SettlementCertificate { + +transition_hash: Hash, // SHA3-256 of the certified transition + +epoch: u64, // Validator set epoch (see SPEC-010) + +votes: Vec\, // Votes from ≥ 2f+1 validators + +} + +struct ValidatorVote { + +validator_id: PublicKey, // Voting validator's public key + +signature: Signature, // Signature over (transition_hash \|\| epoch) + +} + +A settlement certificate is valid if and only if: (a) it contains votes +from at least 2f+1 distinct validators in the epoch's validator set, (b) +all vote signatures are valid, and (c) no equivocation proof exists for +the certified transition. + +Settlement certificates are the fundamental unit of finality in MESH. +Once a valid certificate exists for a transition, that transition is +irreversible. Any participant can independently verify a certificate +without contacting any validator. Certificates are transferable: a +recipient can present a certificate to any third party as proof of +payment. + +**2.6 The Causal Partial Order** + +Transitions in MESH are ordered by causality, not by time. Transition t₁ +causally precedes transition t₂ (written t₁ ≺ t₂) if and only if at +least one of the following holds: + +10. t₂.causal_deps contains the hash of t₁ (direct dependency). + +11. There exists a transition t₃ such that t₁ ≺ t₃ and t₃ ≺ t₂ + (transitive closure). + +12. t₁ and t₂ are on the same account and t₁.sequence \< t₂.sequence + (same-account ordering). + +Two transitions t₁ and t₂ are concurrent (written t₁ \|\| t₂) if neither +t₁ ≺ t₂ nor t₂ ≺ t₁. Concurrent transitions on different accounts can be +processed in any order or in parallel, because they do not affect each +other's validity. + +This causal structure forms a directed acyclic graph (DAG). The graded +structure is defined by the rank function ρ(t) = 1 + max({ρ(d) : d ∈ +t.causal_deps} ∪ {ρ(prev_t) : prev_t is the previous transition on the +same account}), with ρ(genesis) = 0. The rank provides a natural +"logical clock" for the system without requiring synchronised physical +clocks. + +**2.7 The Value Semiring** + +The Value Semiring 𝕍 = (V, ⊕, ⊗, 0, 1) formalises multi-asset value +operations: + +- **V** is the set of all (amount: u128, asset_id: AssetID) pairs. + +- **⊕ (aggregation)**: (a₁, id) ⊕ (a₂, id) = (a₁ + a₂, id). Only + defined for same asset_id. Aggregation of different assets produces + a ValueSet (multiset over V). + +- **⊗ (exchange)**: (a, id₁) ⊗ rate = (a × rate.numerator / + rate.denominator, id₂) where rate is an ExchangeRate from id₁ to + id₂. This models currency conversion. + +- **0**: The zero value (0, any_id). Identity element for ⊕. + +- **1**: The identity exchange rate (numerator = denominator = 1, same + asset). Identity element for ⊗. + +The semiring axioms (associativity, commutativity, distributivity of ⊗ +over ⊕, absorbing zero) guarantee that multi-hop payment path +composition is well-defined and that value conservation can be verified +algebraically. Implementers MUST use exact integer arithmetic (u128) for +all value calculations. Floating-point arithmetic is PROHIBITED. + +**2.8 Serialisation** + +All structures are serialised using a deterministic binary encoding. The +canonical serialisation is the input to all hash and signature +operations. The encoding rules are: + +13. Fixed-size fields are encoded in their natural byte representation + (little-endian for integers). + +14. Variable-length fields (Vec\) are encoded as: length (u32) \|\| + element₁ \|\| element₂ \|\| \... \|\| elementₙ. + +15. Optional fields are encoded as: presence_flag (u8, 0 or 1) \|\| + value (if present). + +16. Structs are encoded as the concatenation of their fields in + declaration order. + +17. Maps are encoded as a sorted (by key) Vec of (key, value) pairs. + +Implementers MUST produce identical byte sequences for identical data. +The canonical serialisation of a structure S is denoted encode(S). The +hash of a structure is hash(S) = SHA3-256(encode(S)). + +**SPEC-003: Tier 1 --- Consensusless Settlement Protocol** + +**3.1 Purpose** + +This specification defines the protocol for simple settlements that do +not require global transaction ordering. Tier 1 handles the common case +of one-to-one and one-to-many payments where the sender is the sole +owner of the transferred value. This is the fast path, designed for +sub-300ms finality in retail payment scenarios. + +Tier 1 is based on Byzantine Consistent Broadcast (Bracha, 1987). The +key insight is that pre-funded, single-owner transfers do not require +consensus because there is no shared state to agree on --- only the +sender's balance needs to be checked, and the sender's account chain is +single-writer. + +**3.2 Preconditions** + +A transition is eligible for Tier 1 processing if and only if ALL of the +following hold: + +18. The transition involves exactly one sender account. + +19. The sender account has sufficient committed balance (verifiable via + range proofs). + +20. The transition does not depend on any uncommitted (pending) + transition from a different account. + +21. The transition does not involve conditional logic (no escrows, no + time-locks beyond the standard expiry). + +If any precondition is not met, the transition MUST be routed to Tier 2. +The routing decision is made by the sender's wallet software, not by +validators. A wallet that incorrectly routes a Tier-2-eligible +transition to Tier 1 will receive rejection from validators +(ERR_TIER1_INELIGIBLE). + +**3.3 Protocol Steps** + +The Tier 1 protocol consists of two phases: Vote Collection and +Certificate Broadcast. The sender coordinates both phases. + +**3.3.1 Phase 1: Vote Collection** + +The sender constructs a valid Transition (per SPEC-002 §2.4) and sends +it to all validators. + +Message: VOTE_REQUEST + +sender → all validators + +payload: Transition + +Upon receiving a VOTE_REQUEST, each correct validator vᵢ performs the +following: + +22. Apply all validation rules from SPEC-002 §2.4.3, in order. + +23. If all checks pass, compute vote_signature = Sign(vᵢ.secret_key, + transition_hash \|\| current_epoch). + +24. Send VOTE_RESPONSE(validator_id, vote_signature) to the sender. + +25. Record (sender, sequence, transition_hash) in local state to enable + equivocation detection. + +If any validation rule fails, the validator sends +VOTE_REJECT(error_code, error_detail) to the sender. The validator MUST +NOT sign a vote for a transition that fails any check. + +> **CRITICAL:** Step 4 is the equivocation lock. Once a validator has +> voted for transition t with (sender, sequence) = (A, 42), it MUST NOT +> vote for any other transition t′ with the same (A, 42). If it receives +> such a request, it MUST respond with ERR_EQUIVOCATION and broadcast an +> equivocation proof. + +**3.3.2 Phase 2: Certificate Assembly and Broadcast** + +The sender collects VOTE_RESPONSE messages. Once the sender has 2f+1 +valid votes from distinct validators, it assembles a +SettlementCertificate. + +Message: SETTLEMENT_CERTIFICATE + +sender → all validators + +payload: SettlementCertificate + +Upon receiving a SETTLEMENT_CERTIFICATE, each correct validator: + +26. Verifies the certificate contains ≥ 2f+1 valid, distinct votes for + the referenced transition hash. + +27. Verifies that all vote signatures are valid under the respective + validator public keys in the current epoch's validator set. + +28. Applies the transition to its local state: debits the sender's + committed balance, credits each recipient's committed balance, + increments the sender's sequence number. + +29. Stores the certificate and its transition as part of the permanent + record. + +After step 3, the transition is final. The sender's balance has been +irrevocably reduced and the recipient's balance has been irrevocably +increased. There is no rollback mechanism. + +**3.3.3 Recipient Notification** + +Recipients learn of incoming payments by one of the following +mechanisms: + +- **Push notification:** Validators MAY push SETTLEMENT_CERTIFICATE + messages to the recipient if the recipient is online and connected + to the validator. + +- **Pull query:** Recipients MAY poll validators for new certificates + addressed to their public key (or stealth addresses --- see + SPEC-007). + +- **Out-of-band:** The sender MAY transmit the certificate directly to + the recipient via any channel (QR code, NFC, Bluetooth, messaging + app). + +The recipient does not need to be online during the settlement. +Certificates are persistent and can be claimed at any time. However, a +recipient MUST submit a Receive transition (with the certificate as a +causal dependency) to update their account state and make the received +funds spendable. + +**3.4 Timing Analysis** + +Under normal network conditions (after GST), the protocol completes in: + + --------------------------- ---------------------- --------------------- + **Step** **Duration** **Cumulative** + + Sender → Validators RTT/2 (≈50ms 50ms + (VOTE_REQUEST) intra-continental) + + Validator processing + ≈10ms per transition 60ms + signing + + Validators → Sender RTT/2 (≈50ms) 110ms + (VOTE_RESPONSE) + + Sender assembles \<1ms 111ms + certificate + + Sender → Validators RTT/2 (≈50ms) 161ms + (CERTIFICATE) + + Validator applies ≈10ms 171ms + transition + --------------------------- ---------------------- --------------------- + +Total wall-clock time from initiation to finality: approximately 170ms +intra-continental. This is well below the 300ms threshold required for +contactless payment terminals and comparable to current card network +authorisation times. + +The sender does not need to wait for all 2f+1 responses; it needs only +the fastest 2f+1. With n validators geographically distributed, the +effective latency is the (2f+1)-th order statistic of the RTT +distribution, not the maximum. + +**3.5 Equivocation Handling** + +An equivocation occurs when a Byzantine sender attempts to issue two +different transitions with the same sequence number, sending each to a +different subset of validators. + +**3.5.1 Detection** + +If a validator vᵢ receives a VOTE_REQUEST for transition t′ with +(sender, sequence) = (A, k), but has already voted for a different +transition t with the same (A, k), then vᵢ constructs an equivocation +proof: + +struct EquivocationProof { + +transition_1: Transition, // First observed transition + +transition_2: Transition, // Conflicting transition + +detector: PublicKey, // Validator that detected equivocation + +detector_sig: Signature, // Validator's signature over the proof + +} + +**3.5.2 Propagation** + +The detecting validator broadcasts the EquivocationProof to all other +validators. Upon receiving a valid equivocation proof, every correct +validator: + +30. Rejects both transitions permanently for this (sender, sequence) + pair. + +31. Revokes any vote previously issued for either transition. + +32. Stores the equivocation proof as permanent evidence. + +An equivocating account's funds are not lost but are frozen at the last +known-good state. The account owner must submit a new transition with +the correct sequence number (skipping the equivocated one) to resume +operations. The protocol MAY impose a cooldown penalty (SPEC-010). + +**3.6 Sharding** + +Tier 1 supports horizontal sharding because each account is independent. +A validator MAY partition its accounts across multiple machines +(shards), each handling a disjoint subset of accounts. The partitioning +function is: shard_id = hash(account_pubkey) mod num_shards. + +Shards operate independently --- they share no state. A settlement +between accounts on different shards requires the sender to contact +validators on the sender's shard only (because only the sender's balance +and sequence number are checked). The recipient's shard learns about the +settlement when the certificate is presented. + +This means throughput scales linearly with the number of shards. A +validator with 16 shards across 16 machines can handle 16× the +throughput of a single machine, with no coordination overhead. + +**SPEC-006: Cryptographic Primitives and Cipher Suites** + +**6.1 Purpose** + +This specification defines all cryptographic operations used by the MESH +protocol. All implementations MUST use the exact algorithms, parameters, +and encodings specified here. Deviations will produce incompatible +signatures and proofs, causing interoperability failures. + +MESH uses a cipher suite abstraction that allows the protocol to upgrade +cryptographic primitives without changing the protocol logic. Each +cipher suite is a complete, internally consistent set of cryptographic +algorithms. + +**6.2 Cipher Suite 0 (Launch Suite)** + +Cipher Suite 0 is the mandatory-to-implement suite for the initial +protocol launch. It uses well-established, patent-free cryptographic +primitives. + + ----------------------- ----------------------------------------------- + **Operation** **Algorithm** + + Digital Signatures Ed25519 (RFC 8032). Curve: Curve25519. Key + size: 32 bytes. Signature size: 64 bytes. + + Key Agreement X25519 (RFC 7748). Ephemeral ECDH for session + key establishment. + + Hash Function SHA3-256 (FIPS 202). Output: 32 bytes. Used for + all content hashing. + + Extendable Output SHAKE256 (FIPS 202). Used for key derivation + and domain separation. + + Symmetric Encryption ChaCha20-Poly1305 (RFC 8439). For memo + encryption and transport layer. + + Commitment Scheme Pedersen Commitments over Curve25519. C = vG + + bH. See SPEC-007. + + Range Proofs Bulletproofs+ over Curve25519. See SPEC-007. + + KDF HKDF-SHA3-256 (adapted from RFC 5869 using + SHA3-256). + ----------------------- ----------------------------------------------- + +**6.3 Cipher Suite 1 (Post-Quantum Hybrid)** + +Cipher Suite 1 adds post-quantum algorithms in a hybrid configuration. +Security holds if either the classical or PQ assumption is unbroken. +This suite is OPTIONAL for launch and MUST be supported within 18 months +of mainnet. + + ----------------------- ----------------------------------------------- + **Operation** **Algorithm** + + Digital Signatures Ed25519 \|\| ML-DSA-65 (FIPS 204). Hybrid: both + signatures are computed and concatenated. + Verification requires BOTH to be valid. + Combined signature size: 64 + 3309 = 3373 + bytes. + + Key Encapsulation X25519 \|\| ML-KEM-768 (FIPS 203). Hybrid KEM: + shared secret = HKDF(X25519_secret \|\| + ML-KEM_secret). Combined ciphertext: 32 + 1088 + = 1120 bytes. + + Hash Function SHA3-256 (unchanged --- already + quantum-resistant). + + Hash-based Signatures SLH-DSA-SHA2-128f (FIPS 205). Used for + (fallback) long-term keys where signature size is less + critical. + + Backup KEM HQC-128 (NIST 5th standard). Used as secondary + KEM for cryptographic diversity. + ----------------------- ----------------------------------------------- + +**6.4 Key Formats** + +**6.4.1 Account Key Pair** + +Each account has a single key pair used for signing transitions and +receiving stealth payments. + +struct AccountKeyPair { + +secret_key: \[u8; 32\], // Ed25519 secret seed + +public_key: \[u8; 32\], // Ed25519 public key = +ScalarBaseMult(secret_key) + +view_key: \[u8; 32\], // For stealth address scanning (see SPEC-007) + +} + +The view_key is derived deterministically: view_key = +HKDF-SHA3-256(secret_key, salt=\"mesh-view-key\", info=\"\", length=32). +The view_key allows a third party (e.g., a watch-only wallet) to detect +incoming payments without the ability to spend them. + +**6.4.2 Validator Key Pair** + +Each validator has a signing key pair for voting on transitions. +Validators MUST use threshold key generation (SPEC-010) so that no +single ceremony participant knows the full secret key. + +**6.5 Domain Separation** + +All hash and signature operations MUST use domain separation to prevent +cross-protocol attacks. The domain separator is a fixed-length prefix +prepended to the input: + +hash_transition = SHA3-256(\"MESH-TRANSITION-V0\" \|\| +encode(transition)) + +hash_certificate = SHA3-256(\"MESH-CERTIFICATE-V0\" \|\| +encode(certificate)) + +hash_equivocation = SHA3-256(\"MESH-EQUIVOCATION-V0\" \|\| +encode(proof)) + +sign_vote = Sign(key, \"MESH-VOTE-V0\" \|\| transition_hash \|\| epoch) + +Domain separators are ASCII strings, NOT null-terminated, and are NOT +length-prefixed (their length is fixed per domain). If a new domain is +added in a future version, it MUST use a unique prefix. + +**6.6 Cipher Suite Negotiation** + +During transport-layer handshake (SPEC-009), peers exchange their +supported cipher suites ordered by preference. The highest-preference +suite supported by both peers is selected. If no common suite exists, +the connection MUST be rejected. + +All validators MUST support Suite 0. Suite 0 MUST remain supported for +at least 5 years after Suite 1 becomes mandatory, to allow migration. A +validator MAY support multiple suites simultaneously and process +transitions from accounts using different suites. + +An account's cipher suite is determined by the format of its public key. +Suite 0 keys are 32 bytes. Suite 1 keys are 32 + 1952 = 1984 bytes +(Ed25519 pubkey \|\| ML-DSA-65 pubkey). The first byte of the key +encoding indicates the suite version. + +**6.7 Constant-Time Requirements** + +All cryptographic operations that process secret data MUST be +implemented in constant time. Specifically: + +- Signature generation MUST NOT have data-dependent branches or memory + access patterns. + +- Key comparison MUST use constant-time byte comparison (e.g., + subtle::ConstantTimeEq in Rust). + +- Commitment generation and range proof computation MUST NOT leak the + committed value through timing. + +Implementations MUST be validated against timing side-channels using +tools such as dudect or ctgrind. The formal verification effort +(SPEC-010 §10.8) SHOULD include verification of constant-time properties +at the assembly level. + +**SPEC-007: Privacy Layer** + +**7.1 Purpose** + +This specification defines the privacy mechanisms that make settlement +amounts and participant identities confidential by default. Every +transition in MESH uses the mechanisms defined here. There is no +\"transparent mode\" --- privacy is not optional. + +**7.2 Pedersen Commitments** + +All value amounts in MESH are represented as Pedersen commitments rather +than plaintext integers. A Pedersen commitment to value v with blinding +factor b is: + +C = v·G + b·H + +where G is the Ed25519 base point and H is a secondary generator point. +The point H MUST be generated via a nothing-up-my-sleeve construction: + +H = HashToCurve(SHA3-256(\"MESH-PEDERSEN-H-V0\")) + +using the hash-to-curve method specified in RFC 9380 (Elligator 2 for +Curve25519). The discrete logarithm of H with respect to G is unknown +and computationally infeasible to determine. This ensures the binding +property: no one can open a commitment to a different value. + +**7.2.1 Commitment Operations** + +Pedersen commitments are additively homomorphic: + +- **Addition:** Commit(v₁, b₁) + Commit(v₂, b₂) = Commit(v₁ + v₂, b₁ + + b₂). This allows validators to verify that inputs equal outputs by + checking that the sum of input commitments equals the sum of output + commitments + fee commitment. + +- **Subtraction:** Commit(v₁, b₁) - Commit(v₂, b₂) = Commit(v₁ - v₂, + b₁ - b₂). Used for balance verification. + +- **Scalar multiplication:** k · Commit(v, b) = Commit(k·v, k·b). Used + for exchange rate application. + +Validators perform conservation checks entirely on commitment points. +They never learn the underlying values. + +**7.2.2 Blinding Factor Management** + +The sender MUST generate a fresh, cryptographically random blinding +factor for every commitment. Blinding factors MUST be generated from a +CSPRNG seeded with at least 256 bits of entropy. Reusing blinding +factors across commitments leaks information about the committed values. + +The sender MUST transmit the blinding factor to the recipient (encrypted +with the recipient's public key) so the recipient can verify and spend +the received funds. The blinding factor is included in the encrypted +memo field of the transition. + +**7.3 Bulletproofs+ Range Proofs** + +A Pedersen commitment hides the value but does not prevent negative +values. Without range proofs, a malicious sender could commit to a +negative amount, effectively creating value from nothing. Bulletproofs+ +range proofs prove that a committed value lies in \[0, 2⁶⁴) without +revealing the value. + +**7.3.1 Parameters** + + ----------------------- ----------------------------------------------- + **Parameter** **Value** + + Curve Curve25519 (Ristretto group for Bulletproofs+) + + Range \[0, 2⁶⁴). All amounts are unsigned 64-bit + integers in base units. + + Proof size (single) Approximately 576-672 bytes depending on the + number of range statements. + + Aggregation Multiple range proofs in a single transition + SHOULD be aggregated into a single proof. + Aggregated proof size is O(log₂(n · 64)) group + elements. + + Proving time Target: \< 500ms on a 2020-era mobile SoC (ARM + Cortex-A78 or equivalent). + + Verification time Target: \< 10ms per proof on validator + hardware. + ----------------------- ----------------------------------------------- + +**7.3.2 Proof Generation** + +The sender generates a Bulletproofs+ range proof for each committed +amount using the Fiat-Shamir heuristic for non-interactivity. The +transcript MUST include the following domain-separated inputs, in order: + +33. The domain separator: \"MESH-BP+-V0\". + +34. The commitment point C (32 bytes, compressed Ristretto). + +35. The transition hash (32 bytes) --- binds the proof to the specific + transition. + +Implementations MUST use the Merlin transcript protocol for Fiat-Shamir +challenges, as specified in the dalek-cryptography Bulletproofs library +documentation. The proof encoding follows the dalek format: +2·⌈log₂(64)⌉ + 2 curve points + 3 scalars. + +**7.4 Stealth Addresses** + +Stealth addresses prevent observers from linking payments to a +recipient's long-term public key. + +**7.4.1 Protocol** + +To send a payment to recipient with public key P_recipient and view key +V_recipient: + +36. Sender generates an ephemeral key pair: (r, R = r·G). + +37. Sender computes shared secret: S = HKDF(r · V_recipient, + salt=\"mesh-stealth\", length=32). + +38. Sender computes one-time stealth address: P_stealth = P_recipient + + SHA3-256(S)·G. + +39. Sender addresses the transition to P_stealth and includes R (the + ephemeral public key) in the encrypted memo. + +To detect incoming payments, the recipient (or a delegated scanner with +the view key): + +40. For each new transition with recipient P_stealth and ephemeral key + R: + +41. Compute S = HKDF(view_key · R, salt=\"mesh-stealth\", length=32). + +42. Compute P_expected = P_recipient + SHA3-256(S)·G. + +43. If P_expected == P_stealth, this payment is for us. The spending key + for this stealth address is: s_stealth = s_recipient + SHA3-256(S), + where s_recipient is the recipient's secret key. + +**7.5 Selective Disclosure** + +When a participant needs to prove properties of their transactions to a +third party (auditor, tax authority, counterparty), they generate a +zero-knowledge proof that reveals only the required information. + +Example disclosure types: + +- **Balance proof:** \"My balance in asset X is at least Y.\" Proven + by opening a range proof on the current balance commitment with a + lower bound. + +- **Transaction history proof:** \"My total outgoing transfers in + period \[t₁, t₂\] were Z.\" Proven by aggregating commitments from + the relevant transitions and opening the aggregate. + +- **Counterparty proof:** \"I paid entity E exactly amount A on date + D.\" Proven by revealing the blinding factor for a specific + transition to the verifier. + +Selective disclosure proofs are generated client-side by the disclosing +party. Validators are not involved. The proofs are standard Schnorr +proofs of knowledge of the opening of Pedersen commitments, which are +straightforward to implement and verify. + +**SPEC-008: Value Routing and Exchange** + +**8.1 Purpose** + +This specification defines how value is routed across multiple hops and +exchanged between different asset types. This is the currency-agnostic +layer that enables MESH to settle any form of value without being tied +to a specific currency. + +**8.2 The MESH Packet** + +Inspired by the Interledger Protocol (ILPv4), MESH routes value in small +packets. Each packet is an independent, atomic unit of value transfer. + +**8.2.1 Packet Structure** + +struct MeshPacket { + +version: u8, + +packet_type: PacketType, // enum: Prepare, Fulfill, Reject + +destination: Address, // MESH address of final recipient + +amount: u128, // Amount in the destination asset's base units + +source_asset: AssetID, // Asset being sent + +dest_asset: AssetID, // Asset to be received + +condition: Hash, // PTLC condition (point, not hash --- see §8.4) + +expiry: u64, // Unix timestamp + +data: \[u8; 32768\], // End-to-end encrypted data (opaque to connectors) + +} + +**8.3 Addressing** + +MESH uses a hierarchical address scheme inspired by IP addresses and ILP +addresses: + +mesh.\.\.\ + +Examples: + +- mesh.mainnet.au-bank-connector.alice --- Alice's account via an + Australian bank connector + +- mesh.mainnet.solar-exchange.grid42 --- Energy grid account via a + solar exchange connector + +Connectors route packets based on address prefixes, similar to IP +routing tables. A connector that handles the prefix +mesh.mainnet.au-bank-connector will accept packets addressed to any +account under that prefix. + +**8.4 Point Time-Locked Contracts (PTLCs)** + +MESH uses PTLCs instead of HTLCs for atomic multi-hop settlement. PTLCs +use adaptor signatures rather than hash preimages, providing two +critical privacy improvements: + +44. **No correlation:** In HTLCs, the same hash preimage is used across + all hops, allowing any observer to link hops in the same payment. In + PTLCs, each hop uses a different adaptor point, making hops + unlinkable. + +45. **Scriptless:** PTLCs do not require the underlying settlement layer + to support hash locks or any scripting. They work with plain Schnorr + signatures, which are supported in Suite 0. + +**8.4.1 PTLC Construction** + +Setup: Sender Alice wants to pay Recipient Bob through Connector +Charlie. + +46. Alice generates a random secret scalar s and computes the + corresponding point Y = s·G. + +47. Alice sends a Prepare packet to Charlie with condition Y. + +48. Charlie generates a new random scalar s′ and computes Y′ = s′·G + Y + (his adaptor is offset from Alice's). + +49. Charlie sends a Prepare packet to Bob with condition Y′. + +50. Bob knows the expected Y′ (communicated by Alice out-of-band in the + encrypted data field). Bob computes the adaptor signature under Y′ + and sends a Fulfill to Charlie. + +51. Charlie uses Bob's adaptor signature to recover s′, then computes + the adaptor signature under Y for Alice. Charlie sends Fulfill to + Alice. + +52. Alice uses Charlie's adaptor signature to recover s, confirming the + payment completed. + +At each hop, the adaptor point is different, so an observer who sees the +(Charlie → Bob) hop cannot link it to the (Alice → Charlie) hop. The +math ensures atomicity: either all hops complete (everyone learns their +respective secrets) or none do (timeouts expire and funds are refunded). + +**8.5 Packet Splitting** + +Large payments are split into small packets to minimise per-packet risk: + +- **Default packet size:** Configurable per connector, recommended + default: 1000 base units of the source asset (\~\$10 AUD at standard + precision). + +- **Parallelism:** Multiple packets MAY be sent simultaneously along + different paths. + +- **Retry:** If a packet is rejected (Reject response), the sender MAY + retry on a different path. + +- **Completion:** The payment is complete when the sender has received + Fulfill for all packets. Partial completion is possible (some + packets fulfilled, others expired). The sender's wallet is + responsible for retrying or notifying the user. + +The recipient's wallet MUST be able to reconstruct the total payment +from individual packets. The sender includes a payment_id and +packet_index in the encrypted end-to-end data of each packet. + +**8.6 On-Ramp and Off-Ramp** + +Value enters and exits the MESH network through on-ramp and off-ramp +connectors. These are connectors that bridge between MESH and external +settlement systems (bank accounts, card networks, mobile money, +blockchains). + +**8.6.1 On-Ramp Protocol** + +53. User deposits value into the on-ramp connector's external account + (e.g., bank transfer). + +54. On-ramp connector verifies the deposit on the external system. + +55. On-ramp connector initiates a Tier 1 settlement crediting the user's + MESH account with the corresponding committed amount. + +56. The on-ramp transition includes a reference to the external deposit + (e.g., bank transaction ID) in the causal_deps field (as an opaque + hash) for auditability. + +On-ramp connectors are trust points: the user must trust the connector +to honour deposits. This is analogous to trusting a bank with a deposit. +The MESH protocol does not eliminate this trust requirement --- it +minimises it by making the on-ramp the only point where external trust +is needed. + +**8.6.2 Off-Ramp Protocol** + +57. User initiates a settlement to the off-ramp connector's MESH + account. + +58. Off-ramp connector receives the settlement certificate. + +59. Off-ramp connector initiates the external transfer (e.g., bank + transfer to user's bank account). + +60. Off-ramp connector provides the user with an external settlement + proof (e.g., bank transaction confirmation). + +The off-ramp connector bears counterparty risk: it has already received +value on MESH and must honour the external transfer. Connectors manage +this risk through reputation, insurance, or regulatory compliance. + +**SPEC-010: Validator Operations and Governance** + +**10.1 Purpose** + +This specification defines validator lifecycle management, the +governance model for protocol upgrades, the fee model, and the formal +verification requirements. Validators are the infrastructure backbone of +MESH. This spec ensures validators are incentivised, accountable, and +replaceable. + +**10.2 Validator Set** + +The validator set is the set of public keys authorised to vote on +settlements. It is defined per epoch. + +**10.2.1 Epochs** + +An epoch is a period during which the validator set is fixed. Epoch +duration is a governance parameter; the recommended initial value is 24 +hours. At each epoch boundary: + +61. The new validator set is computed based on the governance protocol's + decisions. + +62. Validators perform a distributed key generation (DKG) ceremony to + produce new threshold signing keys. + +63. The new epoch is activated when 2f+1 validators have confirmed + readiness. + +**10.2.2 Initial Validator Set** + +The genesis epoch's validator set is hardcoded in the protocol +specification. It consists of 7 validators operated by the founding +organisations. This is an acknowledged centralisation point that is +mitigated by: + +- A public commitment to expand to 21 validators within 12 months of + mainnet launch. + +- A public commitment to transition to reputation-based entry within + 36 months. + +- All validator software, keys (public), and operational procedures + are published. + +- Any single founding validator can be removed by a 5/7 vote of the + remaining validators. + +**10.3 Fee Model** + +Validators are compensated through per-settlement fees paid by the +sender. Fees are denominated in the settlement's asset type (not in a +native token). + +**10.3.1 Fee Structure** + +The fee for a Tier 1 settlement is: fee = max(base_fee, amount × +fee_rate), where: + +- **base_fee:** Minimum fee per settlement. Governance parameter. + Recommended initial value: equivalent of \$0.001 AUD. + +- **fee_rate:** Proportional fee rate. Governance parameter. + Recommended initial value: 0.001% (1 basis point). + +Tier 2 settlements pay 2× the Tier 1 fee (to reflect the higher resource +cost of consensus). Tier 3 settlements pay 3×. + +Fees are committed (Pedersen commitment) just like amounts. Validators +verify the fee meets the minimum using range proofs but do not learn the +exact amount. Fee revenue is distributed equally among all validators in +the epoch. + +**10.4 Governance Protocol** + +Protocol changes follow a structured process: + +**10.4.1 MESH Improvement Proposals (MIPs)** + +64. **Draft:** Anyone may submit a MIP to the public repository. MIPs + must include: motivation, specification changes (in the format of + this document suite), backward compatibility analysis, security + analysis, and formal verification plan. + +65. **Review:** Minimum 30-day public review period. All feedback must + be addressed in writing. + +66. **Formal Verification:** For any MIP affecting Tier 1, 2, or 3 + protocols, the changed properties must be re-verified in TLA+ and/or + Tamarin. Proof artifacts must be published. + +67. **Validator Vote:** 2/3 supermajority of the current validator set + must vote to accept. Voting is on-chain (a Tier 2 settlement to a + governance contract address). + +68. **Activation:** Accepted MIPs are activated at the next epoch + boundary (or a specified future epoch). Validators that have not + upgraded by activation are automatically excluded from the new + epoch's validator set. + +**10.5 Key Management** + +Validator signing keys are generated using a distributed key generation +(DKG) protocol. The DKG ensures: + +- No single party ever knows the full signing key. + +- Any t-of-n subset of validators can produce a valid signature + (threshold t = 2f+1). + +- The key generation ceremony is verifiable: all participants can + confirm the output is correct. + +The specific DKG protocol is Pedersen's DKG (1991) with Feldman's VSS +(1987) for verifiability. These are patent-free, well-studied protocols +with existing open-source implementations. + +**10.6 Formal Verification Requirements** + +The following properties MUST be formally verified before mainnet +launch. "Formally verified" means: a machine-checked proof exists in a +published proof artifact, using one of the specified tools, and the +proof artifact is reproducible from source. + + --------------------------- ------------------ ------------------------- + **Property** **Tool** **Scope** + + No double-spend (SAFETY-1) TLA+ (TLC model Tier 1 protocol state + checker) machine, up to 5 + validators, 3 accounts + + Value conservation TLA+ Tier 1 and Tier 2 + (SAFETY-2) settlement paths + + Liveness (LIVENESS-1) TLA+ Tier 1 protocol, partial + synchrony model + + Signature unforgeability Tamarin Prover Ed25519 + signing/verification + protocol + + Commitment binding Tamarin Prover Pedersen commitment + scheme + + PTLC atomicity Tamarin Prover Two-hop PTLC construction + + Stealth address ProVerif Stealth address + unlinkability generation and detection + protocol + + Key secrecy (DKG) Tamarin Prover Distributed key + generation ceremony + --------------------------- ------------------ ------------------------- + +For each entry in this table, the verification MUST cover: (a) the +stated property holds under the threat model (SPEC-001 §1.4.2), (b) the +property is violated if the threat model assumptions are weakened +(sanity check), and (c) the proof artifact is published alongside the +specification. + +Verification of the implementation (as opposed to the protocol model) is +a continuous process. The reference implementation MUST pass all test +vectors derived from the formal models. Property-based testing (e.g., +using proptest in Rust) MUST cover at least 90% of the protocol state +space as measured by state coverage analysis. + +**10.7 Test Vectors** + +Each specification MUST include a set of test vectors: known +input/output pairs that any conformant implementation MUST produce +identically. Test vectors are provided as JSON files in the protocol +repository under /test-vectors/{spec-id}/. At minimum, each +specification requires: + +- 10 positive test vectors (valid inputs that must be accepted). + +- 10 negative test vectors (invalid inputs that must be rejected with + the specified error code). + +- 5 edge case vectors (boundary conditions, maximum values, empty + collections). + +Test vector files include: the input data (hex-encoded), the expected +output (hex-encoded), and a human-readable description of what the test +verifies. + +**Document Control** + +**Revision History** + + ------------- ------------ --------------- ------------------------------- + **Version** **Date** **Author** **Description** + + 0.1.0 2026-03-09 MESH Foundation Initial draft. Specifications + 001, 002, 003, 006, 007, 008, + 010. + ------------- ------------ --------------- ------------------------------- + +**Outstanding Items** + +- SPEC-004 (Tier 2 DAG-BFT): Draft in progress. Requires clean-room + protocol synthesis from academic literature. + +- SPEC-005 (Tier 3 aBFT): Draft in progress. Protocol selection + pending performance benchmarking. + +- SPEC-009 (Network Transport): Draft in progress. Wire protocol and + peer discovery. + +- Test vectors: To be generated after reference implementation reaches + alpha. + +- Formal verification artifacts: TLA+ models in progress for SPEC-003. + +**References** + +- Bracha, G. (1987). Asynchronous Byzantine agreement protocols. + Information and Computation, 75(2), 130-143. + +- Baudet, M., Danezis, G., Sonnino, A. (2020). FastPay: + High-Performance Byzantine Fault Tolerant Settlement. ACM AFT 2020. + +- Bünz, B., Bootle, J., Boneh, D., Poelstra, A., Wuille, P., + Maxwell, G. (2018). Bulletproofs: Short Proofs for Confidential + Transactions and More. IEEE S&P 2018. + +- Bünz, B., Agrawal, S., Zamani, M., Boneh, D. (2020). Bulletproofs+. + Crypto 2020. + +- FIPS 202: SHA-3 Standard. NIST, 2015. + +- FIPS 203: ML-KEM. NIST, 2024. + +- FIPS 204: ML-DSA. NIST, 2024. + +- FIPS 205: SLH-DSA. NIST, 2024. + +- RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA). + +- RFC 8439: ChaCha20 and Poly1305 for IETF Protocols. + +- RFC 9380: Hashing to Elliptic Curves. + +- Thomas, S., Schwartz, E. (2015). Interledger Protocol (ILP). W3C + Community Group. + +- Pedersen, T.P. (1991). Non-Interactive and Information-Theoretic + Secure Verifiable Secret Sharing. CRYPTO 1991. + +- Feldman, P. (1987). A practical scheme for non-interactive + verifiable secret sharing. FOCS 1987. diff --git a/docs/specs/MESH-Security-Addendum-v0.1.1.md b/docs/specs/MESH-Security-Addendum-v0.1.1.md new file mode 100644 index 0000000..30d4638 --- /dev/null +++ b/docs/specs/MESH-Security-Addendum-v0.1.1.md @@ -0,0 +1,633 @@ +**MESH PROTOCOL** + +*Security Addendum* + +Attack Vector Analysis and Formal Mitigations + +Errata and amendments to SPEC-003, SPEC-007, SPEC-008, SPEC-010 + +Version 0.1.1-draft \| March 2026 + +**Introduction** + +This document identifies seven attack vectors against the MESH protocol +as specified in the v0.1.0 specification suite. For each attack, we +provide: the threat description, the root cause in the existing +specification, the formal mitigation, the specification amendments +required, and the mandatory test assertions. + +All mitigations in this document are MANDATORY amendments to the +referenced specifications. An implementation that passes all v0.1.0 test +vectors but does not implement these mitigations is NON-CONFORMANT. The +version number of the specification suite is incremented to v0.1.1 upon +adoption of this addendum. + +**Severity Classification** + + -------------- ----------- ----------------------------------------------- + **Severity** **Label** **Definition** + + S1 CRITICAL Allows direct theft of funds or creation of + value from nothing. Protocol is broken without + mitigation. + + S2 HIGH Allows economic griefing, denial of service + against specific users, or degrades privacy + guarantees. + + S3 MEDIUM Allows minor economic advantage or information + leakage under specific conditions. + -------------- ----------- ----------------------------------------------- + +**AV-001: Free Option PTLC Griefing Attack** + +**Severity: S2 (HIGH)** + +**1.1 Threat Description** + +A malicious sender initiates a multi-hop payment via PTLCs (SPEC-008 +§8.4) with a long expiry. The Prepare packet locks the connector's +liquidity for the duration of the expiry. The sender then monitors the +market and decides whether to fulfill or abandon the payment based on +whether the exchange rate has moved in their favour. + +This creates a free financial option: the connector bears the full +market risk (their liquidity is locked at a fixed rate) while the sender +has the optionality to walk away at zero cost. Over millions of +transactions, a systematic attacker could extract significant value from +connectors. + +**1.2 Root Cause** + +SPEC-008 §8.2.1 defines an expiry field on MeshPacket but imposes no +constraint on its maximum value and no cost for locking connector +liquidity. The specification is silent on the relationship between +expiry duration and economic cost. + +**1.3 Mitigation** + +Three complementary mechanisms: + +**1.3.1 Maximum Expiry Decay Per Hop** + +Each connector along a payment path MUST reduce the expiry by at least a +minimum decrement. This limits the total lock-up time and ensures that +senders cannot impose arbitrarily long lock-ups. + +> **SPEC-008 AMENDMENT §8.4.5 (NEW):** Each connector MUST set the +> outgoing Prepare packet's expiry to at most: outgoing_expiry = +> incoming_expiry - T_hop, where T_hop is a per-connector configuration +> parameter with a RECOMMENDED minimum of 30 seconds. A connector MUST +> reject an incoming Prepare if incoming_expiry - current_time \< T_hop +> (insufficient time to complete the hop). This creates a hard ceiling +> on total path expiry: max_total_expiry = T_hop × max_path_length. With +> T_hop = 30s and max_path_length = 10 hops, the maximum lock-up is 5 +> minutes. + +**1.3.2 Locking Fee** + +Connectors MAY charge a time-value locking fee that is deducted from the +payment regardless of whether it is fulfilled or rejected. This converts +the free option into a priced option. + +> **SPEC-008 AMENDMENT §8.5.1 (NEW):** A connector MAY specify a +> locking_fee_rate in its published rate information, expressed as basis +> points per second of lock-up time. The locking fee is: locking_fee = +> amount × locking_fee_rate × (expiry - current_time) / 10000. The +> locking fee is deducted from the transferred amount. If the payment is +> fulfilled, the connector receives the locking fee plus the spread. If +> the payment expires, the connector retains the locking fee. The +> sender's wallet MUST account for locking fees when calculating the +> total cost of a payment. + +**1.3.3 Sender Reputation** + +Connectors SHOULD maintain a local reputation score for senders based on +their fulfillment rate. Senders who frequently let payments expire +receive lower priority and wider spreads. + +> **SPEC-008 AMENDMENT §8.5.2 (NEW):** Connectors SHOULD track the ratio +> of fulfilled to expired Prepare packets per sender public key. A +> connector MAY reject Prepare packets from senders whose fulfillment +> rate falls below a configurable threshold (RECOMMENDED: 80% over the +> last 1000 packets). + +**1.4 Test Assertions** + +1. Assert that a connector rejects an incoming Prepare with expiry \> + current_time + T_hop × max_path_length. + +2. Assert that each hop reduces the outgoing expiry by at least T_hop. + +3. Assert that a payment path with 10 hops and T_hop = 30s has a + maximum total lock-up of 300 seconds. + +4. Assert that the locking fee is correctly deducted from the amount + when the payment expires without fulfillment. + +5. Assert that a sender with a 50% fulfillment rate is rejected by a + connector with an 80% threshold. + +**AV-002: Negative Fee Range Proof Bypass** + +**Severity: S1 (CRITICAL)** + +**2.1 Threat Description** + +A sender constructs a transition where the amount commitment is valid +(positive value with valid range proof), but the fee commitment encodes +a negative value. If the conservation check only verifies that +Σ(recipient amounts) + fee = debit amount on the commitment points, and +the fee range proof is missing or weak, the sender effectively increases +their balance by the absolute value of the negative fee. + +Example: Sender has balance 1000. Sender creates a transfer of 1000 to +recipient, with fee = -500. Conservation check passes: 1000 + (-500) = +500. But the sender has only been debited 500 from a balance of 1000, so +they retain 500 extra. The recipient gets 1000. 500 units of value have +been created from nothing. + +**2.2 Root Cause** + +SPEC-002 §2.4.3 specifies RANGE_CHECK (rule 6) and CONSERVATION_CHECK +(rule 7) as separate steps. However, the specification text for +RANGE_CHECK states: "All range proofs MUST verify. This proves all +amounts are non-negative and within the valid range \[0, 2⁶⁴)." The word +"amounts" is ambiguous --- it could be read as referring only to the +recipient amounts, not the fee. This ambiguity is the attack surface. + +**2.3 Mitigation** + +Eliminate the ambiguity with an explicit enumeration of every commitment +that requires a range proof. + +> **SPEC-002 AMENDMENT §2.4.3 Rule 6 (REVISED):** RANGE_CHECK: The +> following range proofs MUST be present and MUST verify: (a) +> transition.range_proof proves transition.amount is in \[0, 2⁶⁴). (b) +> transition.fee_proof proves transition.fee is in \[0, 2⁶⁴). (c) For +> each recipient r in transition.recipients: r.range_proof proves +> r.amount is in \[0, 2⁶⁴). If ANY of these proofs is absent, malformed, +> or fails verification, the validator MUST reject the transition with +> ERR_INVALID_RANGE_PROOF. There are no exceptions. A transition with +> zero fee MUST still include a valid range proof for the zero-value fee +> commitment. +> +> **SPEC-002 AMENDMENT §2.4.3 Rule 7 (CLARIFIED):** CONSERVATION_CHECK: +> The sum of all output commitments MUST equal the input commitment. +> Formally: C_amount = Σ(C_recipient_i) + C_fee. This is verified on the +> commitment points (elliptic curve point addition). The validator MUST +> verify this equation AFTER all range proofs have passed. The +> combination of range proofs (all values non-negative) and conservation +> (inputs = outputs) together guarantee that no value is created or +> destroyed. + +**2.4 Test Assertions** + +6. Assert that a transition with a valid amount range proof but a + missing fee range proof is rejected with ERR_INVALID_RANGE_PROOF. + +7. Assert that a transition with a fee commitment to a negative value + (commitment point C_fee where opening reveals v \< 0) is rejected. + +8. Assert that a transition with fee = 0 still requires a valid range + proof for the zero commitment. + +9. Assert that a transition where Σ(outputs) + fee = input but fee is + negative is rejected (the range proof on fee catches this before the + conservation check). + +10. Assert that crafting a Bulletproofs+ proof for a value outside \[0, + 2⁶⁴) produces a proof that fails verification. + +**AV-003: Causal Dependency Orphan Exploit** + +**Severity: S1 (CRITICAL)** + +**3.1 Threat Description** + +A Byzantine account references a hash in causal_deps that is a +syntactically valid SHA3-256 digest but does not correspond to any +settlement certificate the validator has seen. If the validator only +checks the hash format (32 bytes, non-zero) without verifying that it +corresponds to a real, certified transition, the Byzantine account could +spend funds it never received. + +Worse: if the "ghost" dependency references a fabricated certificate +that credits the attacker with value, the attacker creates money from +nothing by spending against a fictional incoming payment. + +**3.2 Root Cause** + +SPEC-002 §2.4.3 Rule 8 (CAUSAL_CHECK) states: "Every hash in causal_deps +MUST reference a transition that the validator has already processed and +certified." This is correct in intent but insufficiently precise about +what "processed and certified" means. The specification does not mandate +how the validator performs this lookup or what happens during network +partition when a validator may be behind. + +**3.3 Mitigation** + +> **SPEC-002 AMENDMENT §2.4.3 Rule 8 (REVISED):** CAUSAL_CHECK: For +> every hash h in transition.causal_deps, the validator MUST verify +> that: (a) h exists in the validator's local certificate store (a hash +> map keyed by transition hash, populated only when a valid +> SettlementCertificate is received and verified per SPEC-003 §3.3.2), +> AND (b) the referenced transition's effects (credit to the current +> sender) have been applied to the sender's AccountState. If any hash is +> not found in the certificate store, the validator MUST return +> ERR_UNKNOWN_DEPENDENCY. The validator MUST NOT attempt to fetch the +> missing certificate from the network during validation. If a +> dependency is genuinely missing (e.g., due to network delay), the +> sender must retry after the dependency has been disseminated to the +> validator. + +Additionally, the specification must prevent the case where a sender +references a certified transition that does not actually credit them: + +> **SPEC-002 AMENDMENT §2.4.3 Rule 8a (NEW):** +> DEPENDENCY_RELEVANCE_CHECK: For every hash h in +> transition.causal_deps, the validator MUST verify that the referenced +> transition either: (a) has the current sender as a recipient, OR (b) +> is a prior transition by the current sender (same sender public key). +> A transition that references an unrelated third-party certificate as a +> causal dependency MUST be rejected with ERR_IRRELEVANT_DEPENDENCY. +> This prevents an attacker from padding causal_deps with arbitrary +> valid hashes to confuse causal ordering analysis. + +**3.4 Test Assertions** + +11. Assert that a transition referencing a non-existent hash in + causal_deps is rejected with ERR_UNKNOWN_DEPENDENCY. + +12. Assert that a transition referencing a real certificate hash that + does not credit the sender is rejected with + ERR_IRRELEVANT_DEPENDENCY. + +13. Assert that a transition referencing a valid, relevant certificate + is accepted. + +14. Assert that a validator does NOT fetch missing dependencies from the + network during the validation path (no side-effects during + validation). + +**AV-004: Cross-Shard Double-Spend Race** + +**Severity: S1 (CRITICAL) if sharding is incorrectly implemented; +MITIGATED BY DESIGN if spec is followed** + +**4.1 Threat Description** + +A Byzantine sender sends two conflicting transitions (same sequence +number, different recipients) to two different validator shards +simultaneously, hoping that each shard independently certifies a +different transition before the equivocation is detected. + +**4.2 Root Cause** + +SPEC-003 §3.6 defines the sharding function as shard_id = +hash(account_pubkey) mod num_shards. This is correct and ensures all +transitions for a given account go to the same shard. However, the +specification does not explicitly state that this is a SAFETY-CRITICAL +invariant, and does not specify what happens if an implementation uses a +different sharding function. + +**4.3 Mitigation** + +This attack is already mitigated by design in the specification, but the +safety-critical nature of the sharding invariant must be made explicit: + +> **SPEC-003 AMENDMENT §3.6 (REVISED):** SHARDING SAFETY INVARIANT: All +> transitions for a given account MUST be validated by the same set of +> validators/shards. The shard assignment function is: shard_id = +> SHA3-256(account_pubkey)\[0..4\] mod num_shards, where \[0..4\] takes +> the first 4 bytes of the hash as a little-endian u32. This function +> MUST be deterministic, stateless, and identical across all validators. +> A validator MUST reject a VOTE_REQUEST if the sender's account does +> not map to a shard it is responsible for. An implementation that uses +> a different sharding function, or that allows a transition to be +> processed by a non-responsible shard, is NON-CONFORMANT and UNSAFE. +> +> **SPEC-003 AMENDMENT §3.6.1 (NEW):** CROSS-SHARD VERIFICATION: When a +> validator receives a SettlementCertificate for a recipient that maps +> to a different shard, it MUST verify the certificate (signatures, +> quorum) before crediting the recipient. The certificate provides proof +> that the sender's shard has validated and certified the debit. The +> receiving shard does not re-validate the sender's balance or sequence +> number --- it trusts the certificate as proof that the sender's shard +> has done so. This is safe because the sender's shard is the sole +> authority for the sender's account state. + +**4.4 Test Assertions** + +15. Assert that a validator rejects a VOTE_REQUEST if + hash(sender_pubkey) mod num_shards does not match the validator's + shard_id. + +16. Assert that two conflicting transitions from the same sender (same + sequence, different content) sent to the correct shard produce an + equivocation proof. + +17. Assert that a conflicting transition sent to the WRONG shard is + rejected before equivocation detection (at the shard routing check). + +18. Assert that the sharding function is deterministic: the same public + key always produces the same shard_id regardless of when or where it + is computed. + +**AV-005: Multi-Hop Dust Shaving** + +**Severity: S3 (MEDIUM)** + +**5.1 Threat Description** + +A malicious connector in a multi-hop payment path exploits integer +division rounding to pocket small amounts of value ("dust") from each +transaction. When converting between asset types, the exchange +calculation amount_out = amount_in × rate.numerator / rate.denominator +produces a non-integer result that must be truncated. The connector +keeps the fractional remainder. + +At 1 cent per transaction and 1 million transactions per day, this +yields \$10,000/day in stolen dust. + +**5.2 Root Cause** + +SPEC-002 §2.7 defines the Value Semiring's exchange operation as (a, +id₁) ⊗ rate = (a × rate.numerator / rate.denominator, id₂) but does not +specify the rounding rule or what happens to the remainder. + +**5.3 Mitigation** + +> **SPEC-002 AMENDMENT §2.7.1 (NEW):** EXCHANGE ROUNDING RULE: All +> exchange calculations MUST use the following formula: amount_out = +> floor(amount_in × rate.numerator / rate.denominator). The remainder +> is: remainder = amount_in × rate.numerator mod rate.denominator. The +> remainder MUST be returned to the sender (not retained by the +> connector). The sender's wallet MUST verify that amount_out + +> remainder (converted back to the source asset) exactly equals the +> original amount_in. This is enforced at the PTLC fulfillment stage: +> the sender only fulfills the PTLC if the received amount matches +> expectations within a sender-specified tolerance (max_slippage). +> +> **SPEC-008 AMENDMENT §8.2.1 (REVISED):** The MeshPacket Prepare +> message MUST include a new field: min_destination_amount (u128). The +> recipient (or the recipient-side connector) MUST reject the Prepare +> with ERR_BELOW_MINIMUM if the actual delivered amount is less than +> min_destination_amount. This shifts control to the sender: the sender +> specifies the minimum acceptable output, and if any connector along +> the path shaves more than the sender is willing to tolerate, the +> payment fails rather than succeeding with missing value. + +**5.4 Test Assertions** + +19. Assert that for an exchange with rate 3/7 and amount_in = 100, the + result is amount_out = floor(300/7) = 42, remainder = 300 mod 7 = 6. + +20. Assert that the remainder is returned to the sender, not retained by + the connector. + +21. Assert that a Prepare packet with min_destination_amount = 42 and + actual delivery of 41 is rejected with ERR_BELOW_MINIMUM. + +22. Assert that integer overflow in the multiplication amount_in × + rate.numerator is handled (use u256 intermediate or checked + arithmetic). If overflow would occur, the operation MUST fail with + ERR_OVERFLOW rather than silently truncating. + +**AV-006: Epoch-Boundary Replay Attack** + +**Severity: S1 (CRITICAL)** + +**6.1 Threat Description** + +A user collects VOTE_RESPONSE messages from validators in Epoch N but +does not broadcast the SettlementCertificate until Epoch N+1 (or later). +If validators in the new epoch accept certificates signed by the old +epoch's validators, the user could exploit a situation where: (a) a +validator was removed from the set in Epoch N+1 (perhaps for +misbehaviour), and its votes are now suspect, or (b) the validator set +has changed and the "2f+1 quorum" calculated against the new set may not +hold against the old set. + +**6.2 Root Cause** + +SPEC-002 §2.5.1 defines the SettlementCertificate with an epoch field +and states votes must be from validators in that epoch's set. However, +the specification does not define a grace period or cutoff for +cross-epoch certificate acceptance. The specification is silent on what +happens when a certificate arrives after an epoch boundary. + +**6.3 Mitigation** + +> **SPEC-003 AMENDMENT §3.3.2 (REVISED):** EPOCH VALIDATION FOR +> CERTIFICATES: When a validator receives a SettlementCertificate, it +> MUST perform the following epoch check: (a) If certificate.epoch == +> current_epoch: accept and verify votes against the current validator +> set. (b) If certificate.epoch == current_epoch - 1: accept and verify +> votes against the PREVIOUS epoch's validator set. This provides a +> one-epoch grace period for certificates that were assembled just +> before an epoch transition. (c) If certificate.epoch \< +> current_epoch - 1: REJECT with ERR_CERTIFICATE_EXPIRED. Certificates +> more than one epoch old are not accepted. (d) If certificate.epoch \> +> current_epoch: REJECT with ERR_FUTURE_EPOCH. The validator does not +> accept certificates from future epochs. +> +> **SPEC-010 AMENDMENT §10.2.1 (REVISED):** EPOCH STATE RETENTION: +> Validators MUST retain the validator set (public keys) of the +> immediately previous epoch until the end of the current epoch. This +> means at any given time, a validator stores exactly two validator +> sets: the current epoch's and the previous epoch's. Upon transitioning +> to epoch N+1, the validator set for epoch N-1 is discarded. + +**6.4 Test Assertions** + +23. Assert that a certificate from the current epoch is accepted. + +24. Assert that a certificate from epoch N-1 is accepted during epoch N + (grace period). + +25. Assert that a certificate from epoch N-2 is rejected with + ERR_CERTIFICATE_EXPIRED during epoch N. + +26. Assert that a certificate from epoch N+1 is rejected with + ERR_FUTURE_EPOCH during epoch N. + +27. Assert that votes are verified against the CORRECT epoch's validator + set, not the current epoch's set, when the certificate's epoch + differs from the current epoch. + +28. Assert that a certificate assembled with votes from a validator that + was present in epoch N but removed in epoch N+1 is still accepted + during epoch N+1 (grace period) because the votes are valid for + epoch N. + +**AV-007: Stealth Address Unlinkability Breach via Ephemeral Key Reuse** + +**Severity: S2 (HIGH)** + +**7.1 Threat Description** + +If a sender reuses an ephemeral key r when constructing stealth +addresses for two different payments to the same recipient, the +resulting stealth addresses P_stealth_1 and P_stealth_2 will be computed +from the same shared secret S, making them linkable. An observer who +sees the same ephemeral public key R in two different transaction memos +can conclude that both payments went to the same recipient. + +More subtly, even if the ephemeral key is not reused, patterns in the +memo field (identical encrypted payload sizes, timing correlations, or +metadata leakage) could allow statistical linkability analysis. + +**7.2 Root Cause** + +SPEC-007 §7.4.1 step 1 states "Sender generates an ephemeral key pair: +(r, R = r·G)" but does not explicitly mandate that r MUST be fresh +randomness for every payment. The specification assumes correct +implementation but does not defend against implementation errors or +deliberate shortcuts. + +**7.3 Mitigation** + +> **SPEC-007 AMENDMENT §7.4.1 Step 1 (REVISED):** Sender generates an +> ephemeral key pair: r = CSPRNG(32 bytes), R = r·G. The value r MUST be +> generated from a cryptographically secure random number generator for +> EVERY payment. The value r MUST NOT be derived deterministically from +> the payment amount, recipient, or any other predictable input. After +> the Fulfill is received (or the payment expires), the value r MUST be +> securely erased from memory using zeroize. An implementation MUST NOT +> cache, reuse, or persist ephemeral keys across payments. +> +> **SPEC-007 AMENDMENT §7.4.2 (NEW):** EPHEMERAL KEY UNIQUENESS +> ENFORCEMENT: The sender's wallet MUST maintain a Bloom filter (or +> equivalent probabilistic set) of recently used ephemeral public keys +> R. Before using a new R, the wallet MUST check that R is not in the +> filter. If a collision is detected (which should only occur due to a +> CSPRNG failure), the wallet MUST generate a new r and retry. The Bloom +> filter SHOULD retain entries for at least 10,000 recent payments. This +> provides defence-in-depth against CSPRNG failures. +> +> **SPEC-007 AMENDMENT §7.4.3 (NEW):** MEMO PADDING: The encrypted memo +> field MUST be padded to a fixed length before encryption, regardless +> of the actual payload size. The padded length MUST be one of: 64, 128, +> 256, 512, 1024, or 2048 bytes (the smallest size that fits the +> payload). This prevents an observer from correlating transactions by +> memo ciphertext length. Padding MUST use random bytes (not +> zero-padding) to prevent distinguishing padding from payload without +> the decryption key. + +**7.4 Test Assertions** + +29. Assert that two payments to the same recipient produce different + stealth addresses (P_stealth_1 ≠ P_stealth_2). + +30. Assert that two payments to the same recipient produce different + ephemeral public keys (R_1 ≠ R_2). + +31. Assert that an observer with access to all SettlementCertificates + but without any view_key cannot determine if two stealth addresses + belong to the same recipient, with advantage ≤ negligible (formal: + advantage \< 2⁻¹²⁸). + +32. Assert that the Bloom filter detects a deliberately reused ephemeral + key and forces regeneration. + +33. Assert that the encrypted memo is padded to a fixed size: a 10-byte + payload and a 100-byte payload to the same recipient produce memos + of the same ciphertext length. + +34. Assert that the ephemeral secret r is zeroed from memory after use + (test via memory inspection in debug mode). + +**Summary of Specification Amendments** + + ------------ -------------- ---------------------- ------------------------------- + **Attack** **Severity** **Amended Spec** **Key Change** + + AV-001 S2 SPEC-008 §8.4.5, Maximum expiry decay per hop, + §8.5.1, §8.5.2 locking fee, sender reputation + scoring. + + AV-002 S1 SPEC-002 §2.4.3 Rules Explicit enumeration of all + 6--7 commitments requiring range + proofs, including fee. + Zero-value fee requires proof. + + AV-003 S1 SPEC-002 §2.4.3 Rules Certificate store lookup + 8--8a mandatory; new relevance check + prevents referencing unrelated + certificates. + + AV-004 S1\* SPEC-003 §3.6, §3.6.1 Sharding invariant made + explicit as safety-critical. + Cross-shard credit via + certificate verification. + + AV-005 S3 SPEC-002 §2.7.1, Rounding rule: floor + + SPEC-008 §8.2.1 remainder to sender. + min_destination_amount field in + Prepare packets. + + AV-006 S1 SPEC-003 §3.3.2, One-epoch grace period for + SPEC-010 §10.2.1 certificates. Strict rejection + of certificates more than one + epoch old. + + AV-007 S2 SPEC-007 §7.4.1--7.4.3 Mandatory fresh CSPRNG + ephemeral key, Bloom filter + uniqueness check, random-padded + memo to fixed lengths. + ------------ -------------- ---------------------- ------------------------------- + +*\* AV-004 is mitigated by design if the specification is followed. The +severity rating reflects the consequence of non-conformant +implementation, not a flaw in the protocol.* + +**Formal Verification Additions** + +The following properties MUST be added to the formal verification +requirements in SPEC-010 §10.6: + + ------------------------- ----------------- ---------------------------- + **Property** **Tool** **Scope** + + Fee commitment range TLA+ Verify that no state is + (AV-002) reachable where a transition + with negative fee commitment + passes all validation rules. + + Causal dependency TLA+ Verify that no state is + integrity (AV-003) reachable where an account + spends value credited by an + uncertified or irrelevant + transition. + + Sharding safety (AV-004) TLA+ Verify that no state is + reachable where two + conflicting transitions for + the same account are + certified by different + shards. + + Epoch-boundary TLA+ Verify that a certificate + certificate validity from epoch N-2 cannot be + (AV-006) applied in epoch N under any + message ordering. + + Stealth address ProVerif Verify the PRIVACY-2 + unlinkability (AV-007) property: an observer + without the view_key has + negligible advantage in + linking two stealth + addresses to the same + recipient. + ------------------------- ----------------- ---------------------------- + +**Document Control** + + ------------- ------------ --------------- ------------------------------- + **Version** **Date** **Author** **Description** + + 0.1.1 2026-03-11 MESH Foundation Security addendum. Mitigations + for 7 identified attack vectors + (AV-001 through AV-007). + ------------- ------------ --------------- ------------------------------- diff --git a/docs/specs/MESH-Specification-Addendum-SPEC-004-005-009.md b/docs/specs/MESH-Specification-Addendum-SPEC-004-005-009.md new file mode 100644 index 0000000..9141314 --- /dev/null +++ b/docs/specs/MESH-Specification-Addendum-SPEC-004-005-009.md @@ -0,0 +1,826 @@ +**MESH PROTOCOL** + +*Specification Suite --- Addendum* + +SPEC-004: Tier 2 DAG-BFT \| SPEC-005: Tier 3 aBFT \| SPEC-009: Network +Transport + +Version 0.1.0-draft \| March 2026 + +**Table of Contents** + +**SPEC-004: Tier 2 --- DAG-BFT Ordered Settlement** + +**4.1 Purpose** + +This specification defines the consensus protocol for settlements that +require global transaction ordering. Tier 2 handles the minority of +transactions where multiple parties contend over shared state: +multi-party atomic swaps, conditional settlements, cross-currency batch +auctions, and escrow operations with multiple possible outcomes. + +Tier 2 is a clean-room DAG-based Byzantine Fault Tolerant consensus +protocol synthesised from the published academic literature on +uncertified DAG BFT. It achieves 3 message delay commit latency in the +common case and provides censorship resistance through its leaderless, +all-to-all communication pattern. + +**4.2 Design Rationale** + +**Why DAG-based?** Traditional leader-based BFT protocols (PBFT, +HotStuff) bottleneck on a single leader for each round. DAG-based +protocols allow every validator to propose blocks simultaneously, +achieving higher throughput. The DAG structure also provides natural +censorship resistance: a Byzantine leader in a traditional protocol can +selectively exclude transactions, but in a DAG every validator +independently includes transactions. + +**Why uncertified?** Certified DAG protocols (DAGRider, Narwhal-Tusk, +Bullshark) require 3 additional message delays per round to certify each +block (broadcast → acknowledge → aggregate certificate). Uncertified +DAGs skip certification entirely: a block is simply broadcast and +referenced by later blocks. Equivocation is handled by the commit rule +rather than by pre-certification. This reduces round latency from 3 +message delays to 1. + +**Why not use existing implementations?** Mysticeti (Mysten Labs), +Shoal++ (Aptos/Diem heritage), and Mahi-Mahi are all implemented by +well-funded companies that may hold process patents on specific +optimisations. MESH's Tier 2 protocol is designed from the published +academic principles, avoiding any specific patented technique while +achieving comparable performance characteristics. + +**4.3 DAG Structure** + +**4.3.1 DAG Block** + +struct DAGBlock { + +author: PublicKey, // Proposing validator + +round: u64, // Logical round number + +references: Vec\, // Hashes of blocks from round-1 (\>= 2f+1 +required) + +weak_refs: Vec\, // Hashes of blocks from earlier rounds +(optional) + +settlements: Vec\, // Ordered list of Tier 2 settlements + +timestamp: u64, // Validator's local time (advisory only, not trusted) + +signature: Signature, // Author's signature over all above fields + +} + +**4.3.2 Round Progression** + +The DAG progresses in logical rounds. In each round, every correct +validator proposes exactly one block. A validator MAY advance to round +r+1 only after receiving blocks from at least 2f+1 distinct validators +in round r. This ensures that each round's blocks collectively reference +a quorum of the previous round, preventing Byzantine validators from +advancing the DAG unilaterally. + +Formally, let B(v, r) denote the block proposed by validator v in round +r. The reference set of B(v, r) MUST satisfy: + +- \|references\| ≥ 2f+1, where each reference is a hash of a block + from round r-1. + +- No two references point to blocks by the same author (prevents + referencing equivocating blocks). + +- The validator MUST have received the full content of each referenced + block (not just the hash). + +**4.3.3 Equivocation in the DAG** + +A Byzantine validator may attempt to propose two different blocks for +the same round (equivocation). In an uncertified DAG, this is not +prevented at the block level. Instead, the commit rule handles +equivocation: + +1. If a correct validator v receives two blocks B₁ and B₂ from the same + author a for the same round r, v records both as an equivocation and + MUST NOT reference either in its own blocks. + +2. The equivocating validator's blocks are excluded from the commit + rule for round r. This means the equivocator cannot benefit from + equivocation. + +3. Equivocation evidence (both blocks) is included in v's next block as + a protocol message, alerting all validators. + +**4.4 Commit Rule** + +The commit rule determines when a block in the DAG is considered final. +This is the most critical component of the consensus protocol. MESH uses +a multi-leader commit rule that can commit multiple blocks per round, +maximising throughput. + +**4.4.1 Leader Selection** + +Each round has a predetermined set of leader validators. The leader for +round r is determined by a rotating schedule: + +leader(r) = validators\[r mod n\] + +where validators is the ordered list of validator public keys in the +current epoch. This is deterministic and known to all validators before +the round begins. A round's leader block is the block proposed by the +leader validator for that round. + +**4.4.2 Direct Commit (Fast Path)** + +A leader block B(leader, r) is directly committed if the following +conditions hold: + +4. **Support condition:** At least 2f+1 blocks in round r+1 reference + B(leader, r) in their references set. + +5. **No equivocation:** The leader validator did not equivocate in + round r (no second block exists). + +6. **Availability:** The full content of B(leader, r) is available to + the committing validator. + +When a validator observes these conditions (which it can determine +locally after receiving 2f+1 blocks from round r+1), it commits +B(leader, r) and all transactions within it. This achieves commit +latency of 3 message delays from when the leader's block is first +broadcast: 1 delay for the block to propagate, 1 delay for round r+1 +blocks to be proposed, and 1 delay for the round r+1 blocks to propagate +back. + +**4.4.3 Indirect Commit (Anchor Chain)** + +Blocks that are not leader blocks are committed indirectly through the +causal history of committed leader blocks. When a leader block B(leader, +r) is committed, all blocks in its causal history that have not yet been +committed are also committed, in causal order. + +Formally, when B(leader, r) is committed, the following set is +committed: + +commit_set(B) = { B\' : B\' is in the causal history of B and B\' is not +yet committed } + +The causal history of B is the transitive closure of B's references. +This means a single leader commit can commit hundreds of blocks from +earlier rounds, amortising the commit latency across many transactions. + +**4.4.4 Skip Rule (Liveness)** + +If a leader's block for round r does not achieve the direct commit +condition (e.g., the leader is Byzantine and equivocated, or the +leader's block was not received by enough validators), the protocol +proceeds to round r+1 with a new leader. The skipped leader's block (if +it exists and is non-equivocating) will be committed indirectly when a +subsequent leader commits. + +To ensure liveness under Byzantine leaders, each correct validator sets +a timeout T_round for receiving the current leader's block. If the +timeout expires, the validator advances to the next round without +referencing the missing leader block. The timeout is calibrated to: + +T_round = max(4 × median_RTT, 500ms) + +where median_RTT is the median observed round-trip time to other +validators. This ensures that under normal network conditions, the +timeout does not fire (avoiding unnecessary leader skips), but under +sustained leader failure, progress continues within at most T_round. + +**4.5 Transaction Ordering** + +Once a set of blocks is committed, the transactions within them must be +deterministically ordered. All validators MUST produce the identical +ordering for the same set of committed blocks. + +**4.5.1 Ordering Algorithm** + +7. Start with the set of blocks to be ordered (the commit_set from + §4.4.3). + +8. Topologically sort the blocks by their causal relationships (if B₁ + is referenced by B₂, B₁ comes first). + +9. Break ties (blocks at the same causal level with no ordering between + them) by sorting on block hash (SHA3-256 of the serialised block), + lexicographically ascending. + +10. Concatenate the transaction lists from each block in the determined + order. + +11. Remove duplicate transactions (same transition hash appearing in + multiple blocks). The first occurrence is kept; later occurrences + are discarded. + +This produces a deterministic, total order over all transactions in the +committed set. The tie-breaking by hash ensures fairness: no validator +can predict which block will come first (because the hash depends on the +full block content), preventing ordering manipulation. + +**4.6 Integration with Tier 1** + +Tier 1 and Tier 2 operate concurrently on the same validator set. The +interaction rules are: + +- **Tier 1 certificates are included in DAG blocks:** Validators + include recently received Tier 1 settlement certificates in their + DAG blocks. This does not re-order the Tier 1 settlements (they are + already final), but it checkpoints them into the ordered history for + auditability and epoch management. + +- **Tier 2 settlements may depend on Tier 1 certificates:** A Tier 2 + transition's causal_deps field may reference Tier 1 settlement + certificate hashes. This enables composable operations: e.g., a + multi-party escrow that depends on a prior simple payment. + +- **Conflict between tiers:** If a Tier 2 settlement conflicts with a + Tier 1 settlement on the same account (both spending the same + balance), the Tier 1 settlement takes priority because it was + certified first. The conflicting Tier 2 settlement is rejected with + ERR_BALANCE_SPENT. + +**4.7 Timing Analysis** + + --------------------------- ---------------------- --------------------- + **Step** **Duration** **Cumulative** + + Leader broadcasts block RTT/2 (≈50ms) 50ms + (round r) + + Validators receive block, ≈10ms processing 60ms + include in round r+1 refs + + Validators broadcast round RTT/2 (≈50ms) 110ms + r+1 blocks + + Committing validator RTT/2 (≈50ms) 160ms + receives 2f+1 round r+1 + blocks + + Commit rule evaluation \<1ms 161ms + + Transaction execution ≈10ms per batch 171ms + --------------------------- ---------------------- --------------------- + +Total commit latency: approximately 170ms in the common case (non-faulty +leader, synchronous network). This is 3 message delays, matching the +theoretical lower bound for BFT consensus. Under Byzantine leader or +network delay, fallback adds one round per skipped leader, plus T_round +timeout. + +Throughput: each round commits all transactions from all validators' +blocks, not just the leader's. With n=21 validators each proposing +blocks containing up to 10,000 transactions, each round commits up to +210,000 transactions. At one round per \~170ms, steady-state throughput +exceeds 1,000,000 TPS (theoretical). Practical throughput is bounded by +bandwidth and execution, expected to be 100,000-300,000 TPS. + +**4.8 Formal Safety and Liveness Properties** + +> **SAFETY (Tier 2):** If two correct validators commit transaction +> sequences S₁ and S₂, then one is a prefix of the other. That is, +> correct validators never disagree on the ordering of committed +> transactions. This holds as long as f \< n/3 validators are Byzantine, +> under the partial synchrony model. +> +> **LIVENESS (Tier 2):** After GST, every valid Tier 2 settlement +> submitted to a correct validator is committed within O(f × T_round) +> time. In the common case (non-faulty leader), commit occurs within 3Δ. +> Under sustained Byzantine leaders, at most f consecutive leaders can +> be skipped before a correct leader is reached. +> +> **CENSORSHIP RESISTANCE:** A Byzantine leader cannot prevent a +> transaction from being committed. Even if a leader excludes a +> transaction from its block, any of the other n-1 validators can +> include it in their block, and it will be committed when the next +> leader's block is committed (via indirect commit). + +**SPEC-005: Tier 3 --- Asynchronous BFT Fallback** + +**5.1 Purpose** + +This specification defines the fallback consensus protocol that +activates when the network conditions degrade below what Tier 2's +partial synchrony assumption requires. Tier 3 provides liveness +guarantees under full asynchrony: it makes no assumptions about message +delivery times, and guarantees that transactions will eventually be +committed even if an adversary controls the network scheduler. + +Tier 3 is the safety net. It is slower than Tier 2 (expected 1-3 seconds +latency) but guarantees the system never halts. In a well-functioning +network, Tier 3 is never activated. It exists to handle scenarios such +as: submarine cable cuts, major cloud provider outages, targeted network +partitions, or sustained DDoS attacks against specific validators. + +**5.2 Activation Conditions** + +Tier 3 activates automatically when Tier 2 fails to make progress. +Specifically: + +12. **Timeout detection:** If a validator has not observed a new Tier 2 + leader commit for 3 × T_round consecutive rounds (approximately 1.5 + seconds at default settings), it enters Tier 3 mode. + +13. **Quorum detection:** If a validator receives Tier 3 activation + messages from f+1 distinct validators, it enters Tier 3 mode + regardless of its own timeout state. This prevents split-brain where + some validators are in Tier 2 and others in Tier 3. + +14. **Manual activation:** A governance action (SPEC-010) can force Tier + 3 activation for the entire network. This is for emergency + scenarios. + +Tier 3 deactivates when the Tier 3 protocol commits a special RESUME +block, after which validators return to Tier 2. The RESUME block is +proposed when a validator has observed 2f+1 successful message exchanges +within Δ time (evidence that partial synchrony has restored). + +**5.3 Protocol Design** + +MESH's Tier 3 is an asynchronous DAG-based BFT protocol. It reuses the +same DAG structure as Tier 2 (same block format, same reference rules) +but replaces the deterministic commit rule with a randomised commit rule +that works under full asynchrony. + +**5.3.1 Random Coin** + +The fundamental difference between partially synchronous and +asynchronous BFT is the need for a random coin. Fischer, Lynch, and +Paterson (1985) proved that deterministic asynchronous consensus is +impossible with even one faulty process. The random coin breaks this +impossibility. + +MESH uses a threshold random coin constructed from threshold BLS +signatures. In each round: + +15. Each validator computes a partial coin share: shareᵢ = BLS_Sign(skᵢ, + round_number). + +16. Once 2f+1 shares are collected, the coin is reconstructed: coin(r) = + least_significant_bit(BLS_Aggregate(shares)). + +17. The coin is unpredictable: no coalition of fewer than f+1 validators + can predict the coin's value before it is revealed. + +The BLS threshold signature scheme is used solely for the random coin in +Tier 3. It is not used in Tier 1 or Tier 2. This isolates the (slightly +more complex) BLS dependency to the fallback path. + +> **IMPLEMENTATION NOTE:** The BLS signature scheme uses the BLS12-381 +> curve. Implementations MUST use a pairing-friendly curve library that +> has been audited for correctness. The threshold DKG for BLS keys is +> performed during epoch setup alongside the Ed25519 DKG (SPEC-010). + +**5.3.2 Commit Rule (Asynchronous)** + +The asynchronous commit rule operates in waves. Each wave spans two +rounds of the DAG (an even round and the following odd round). + +18. **Vote round (even):** In round 2k, each validator proposes a block + as normal. The leader for wave k is determined by: leader(k) = + validators\[coin(2k) mod n\], using the random coin revealed at the + start of round 2k. Note: the leader is determined after the round's + blocks are proposed, preventing a Byzantine adversary from + selectively withholding the leader's block. + +19. **Decide round (odd):** In round 2k+1, validators check whether the + wave-k leader's block from round 2k was referenced by 2f+1 blocks in + round 2k. If yes, the leader block is committed (along with its + causal history). If no, the wave is skipped and the protocol + proceeds to wave k+1. + +The key insight: because the leader is chosen randomly after blocks are +proposed, a Byzantine adversary cannot know which block to suppress +until it is too late. With probability at least 2/3 (when the coin +selects a correct validator), the leader's block will have been received +and referenced by a quorum, and the wave commits. + +**5.3.3 Expected Latency** + +Under full asynchrony, the expected number of waves until a commit is: + +E\[waves\] = 1 / P(correct_leader_and_referenced) = 1 / (2/3 × 2/3) ≈ +2.25 waves + +Each wave is 2 rounds. Each round is bounded by the network's actual +message delivery time (not a pre-set timeout). In practice, even under +adversarial scheduling, expected commit latency is 4-6 round-trips, +approximately 1-3 seconds on continental networks. + +This is significantly slower than Tier 2's 170ms but is acceptable +because Tier 3 only activates during exceptional network conditions. The +important property is that it always terminates --- there is no scenario +under the threat model where Tier 3 fails to make progress. + +**5.4 Data Structures** + +**5.4.1 Tier 3 Activation Message** + +struct Tier3Activation { + +validator: PublicKey, + +last_tier2_commit: Hash, // Hash of last committed Tier 2 leader block + +round: u64, // Current DAG round at activation + +reason: ActivationReason, // enum: Timeout, QuorumDetected, Manual + +signature: Signature, + +} + +**5.4.2 Coin Share** + +struct CoinShare { + +validator: PublicKey, + +round: u64, + +share: BLSSignature, // 96 bytes (BLS12-381 G2 point) + +} + +**5.5 Integration with Tier 2** + +Tier 3 operates on the same DAG as Tier 2. When Tier 3 activates: + +20. The DAG continues to grow --- blocks are still proposed and + referenced. + +21. The Tier 2 commit rule is suspended (no deterministic leader + commits). + +22. The Tier 3 commit rule is applied instead (random leader via coin). + +23. Transactions committed by Tier 3 are added to the same ordered + history as Tier 2 commits. + +24. When Tier 3 deactivates (RESUME block), the Tier 2 commit rule + resumes from the current round. + +The transition is seamless: clients do not need to know which tier +committed their transaction. The settlement certificate format is +identical. The only visible difference is higher latency during the Tier +3 period. + +**5.6 Formal Properties** + +> **SAFETY (Tier 3):** If two correct validators commit transaction +> sequences S₁ and S₂ during Tier 3 operation, one is a prefix of the +> other. This holds under full asynchrony with f \< n/3 Byzantine +> validators. No timing assumptions are required for safety. +> +> **LIVENESS (Tier 3):** Every valid settlement submitted to a correct +> validator during Tier 3 operation is committed with probability 1 +> (almost surely). The expected number of waves is at most +> 3/(2·(1-f/n)²). With n=21 and f=7, this is ≈2.25 waves. +> +> **AGREEMENT (Coin):** The threshold random coin satisfies agreement +> (all correct validators observe the same coin value), unpredictability +> (no coalition of ≤ f validators can predict the coin before 2f+1 +> shares are revealed), and termination (the coin is always produced if +> 2f+1 validators are correct). + +**SPEC-009: Network Transport and Peer Discovery** + +**9.1 Purpose** + +This specification defines the wire protocol, message framing, +connection management, peer discovery, and network-level security +mechanisms for MESH. All communication between validators, and between +clients and validators, uses the transport layer defined here. + +**9.2 Transport Protocol** + +MESH uses QUIC (RFC 9000) as its transport protocol. QUIC is chosen over +TCP for the following reasons: + +- **Multiplexed streams:** QUIC supports multiple independent streams + within a single connection, eliminating head-of-line blocking. This + allows Tier 1 vote requests, Tier 2 DAG blocks, and Tier 3 coin + shares to flow independently without interfering with each other. + +- **Built-in encryption:** QUIC mandates TLS 1.3 for all connections. + There is no unencrypted mode. This simplifies the security model. + +- **Connection migration:** QUIC connections survive IP address + changes, which is important for mobile clients and cloud-based + validators that may be rescheduled. + +- **0-RTT resumption:** Returning clients can send data in the first + packet, reducing latency for repeat connections. + +Implementations MUST use QUIC with TLS 1.3 and MUST NOT fall back to +TCP+TLS. The TLS handshake MUST use the cipher suites specified in +SPEC-006 for the key exchange component. + +**9.3 Connection Establishment** + +**9.3.1 Handshake** + +When a node connects to another node, the following handshake occurs +within the TLS 1.3 handshake: + +25. The initiator sends a ClientHello with ALPN (Application-Layer + Protocol Negotiation) identifier \"mesh/0\". + +26. The responder validates the ALPN and responds with ServerHello. + +27. TLS 1.3 key exchange completes (using X25519 or hybrid + X25519+ML-KEM-768 per SPEC-006). + +28. The initiator sends a MESH HandshakeMessage containing: protocol + version, supported cipher suites (ordered by preference), node type + (validator/client/connector), node public key, and a signature + proving ownership of the public key. + +29. The responder validates the HandshakeMessage and responds with its + own HandshakeMessage. + +30. Both sides verify: (a) the remote node's public key is valid, (b) if + the remote claims to be a validator, its public key is in the + current epoch's validator set, (c) the signature is valid. + +If any check fails, the connection MUST be closed with an error code. No +protocol messages are exchanged before the handshake completes. + +**9.3.2 HandshakeMessage Structure** + +struct HandshakeMessage { + +version: u8, // Protocol major version + +cipher_suites: Vec\, // Supported cipher suite IDs, preference +order + +node_type: NodeType, // enum: Validator, Client, Connector + +public_key: PublicKey, // Node's identity key + +epoch: u64, // Node's current epoch number + +features: u64, // Bitmask of supported optional features + +timestamp: u64, // Current time (used to reject stale handshakes) + +signature: Signature, // Sign(identity_key, all_above_fields) + +} + +**9.4 Message Framing** + +All MESH protocol messages are encoded as length-prefixed frames on a +QUIC stream: + +\[length: u32\] \[message_type: u8\] \[payload: bytes\] + +The length field includes the message_type byte and the payload. Maximum +frame size is 4 MB (4,194,304 bytes). Messages larger than this MUST be +fragmented at the application layer. + +**9.4.1 Message Types** + + --------- ------------------------ -------------------------------------------- + **Type **Name** **Description** + ID** + + 0x01 VOTE_REQUEST Tier 1: Client → Validator. Contains a + Transition. + + 0x02 VOTE_RESPONSE Tier 1: Validator → Client. Contains a + ValidatorVote or rejection. + + 0x03 SETTLEMENT_CERTIFICATE Tier 1: Client → Validator. Contains a + SettlementCertificate. + + 0x04 EQUIVOCATION_PROOF Any → Any. Contains an EquivocationProof. + + 0x10 DAG_BLOCK Tier 2: Validator → Validator. Contains a + DAGBlock. + + 0x11 BLOCK_REQUEST Tier 2: Validator → Validator. Request a + missing block by hash. + + 0x12 BLOCK_RESPONSE Tier 2: Validator → Validator. Response with + requested block. + + 0x20 TIER3_ACTIVATION Tier 3: Validator → Validator. + Tier3Activation message. + + 0x21 COIN_SHARE Tier 3: Validator → Validator. CoinShare for + random coin. + + 0x30 PACKET_PREPARE Routing: Connector → Connector. MeshPacket + (Prepare type). + + 0x31 PACKET_FULFILL Routing: Connector → Connector. MeshPacket + (Fulfill type). + + 0x32 PACKET_REJECT Routing: Connector → Connector. MeshPacket + (Reject type). + + 0x40 HANDSHAKE Connection setup. HandshakeMessage. + + 0x41 PING Keepalive. Empty payload. + + 0x42 PONG Keepalive response. Empty payload. + + 0xF0 QUERY_ACCOUNT Client → Validator. Request current account + state. + + 0xF1 QUERY_RESPONSE Validator → Client. Response with account + state. + + 0xFF ERROR Any → Any. Protocol error with error code + and description. + --------- ------------------------ -------------------------------------------- + +**9.5 Stream Multiplexing** + +MESH uses dedicated QUIC streams for different message categories to +prevent interference: + + --------------- ----------------------- ------------------------------- + **Stream ID **Purpose** **Priority** + Range** + + 0-3 Handshake and keepalive Highest. Must not be blocked by + (PING/PONG) data streams. + + 4-7 Tier 1 messages High. Retail payment + (VOTE_REQUEST, latency-critical. + VOTE_RESPONSE, + CERTIFICATE) + + 8-11 Tier 2 DAG messages Medium. Consensus throughput. + (DAG_BLOCK, + BLOCK_REQUEST, + BLOCK_RESPONSE) + + 12-15 Tier 3 messages Medium. Only active during + (ACTIVATION, fallback. + COIN_SHARE) + + 16-19 Routing messages Normal. Value routing. + (PACKET_PREPARE, + FULFILL, REJECT) + + 20-23 Query messages Low. Client state queries. + (QUERY_ACCOUNT, + QUERY_RESPONSE) + --------------- ----------------------- ------------------------------- + +QUIC stream priorities SHOULD be configured to match the priority +column. Under congestion, Tier 1 messages SHOULD be prioritised over +Tier 2, which SHOULD be prioritised over routing, which SHOULD be +prioritised over queries. + +**9.6 Peer Discovery** + +**9.6.1 Validator Discovery** + +Validators discover each other through a static bootstrap list plus a +gossip protocol: + +31. **Bootstrap:** Each validator is configured with a list of at least + 3 bootstrap nodes (addresses and public keys). These are hardcoded + for the genesis epoch and updated via governance for subsequent + epochs. + +32. **Gossip:** Upon connecting to a bootstrap node, the validator + requests the current validator set (public keys and network + addresses). Validators gossip peer information with a pull-based + protocol: every 30 seconds, a validator requests the peer list from + a randomly chosen connected peer. + +33. **Verification:** All validator addresses are signed by the + validator's identity key. A validator MUST verify the signature + before connecting to a new peer. This prevents man-in-the-middle + injection of fake validator addresses. + +**9.6.2 Client Discovery** + +Clients discover validators through: + +- **Well-known URI:** Each MESH network publishes a validator list at + a well-known HTTPS URL (e.g., + https://mesh-mainnet.org/.well-known/mesh-validators.json). The JSON + document contains: epoch number, validator public keys, network + addresses, and is signed by the governance multisig key. + +- **DNS:** Validator addresses are published as DNS SRV records under + \_mesh.\_quic.\.mesh-protocol.org. This provides a + fallback if the HTTPS endpoint is unavailable. + +- **QR code:** For initial onboarding, a validator's connection + details can be encoded in a QR code for scanning by a mobile wallet. + +**9.7 Eclipse Attack Resistance** + +An eclipse attack occurs when an adversary surrounds a target node with +malicious peers, controlling all of the target's connections. MESH +mitigates eclipse attacks through: + +34. **Minimum connection diversity:** Each validator MUST maintain + connections to at least 2f+1 distinct validators. If the connection + count drops below this, the validator MUST attempt to reconnect + using the bootstrap list. + +35. **Connection rotation:** Every epoch, each validator drops its + lowest-quality connection (highest latency or most dropped messages) + and replaces it with a randomly selected validator from the current + set that it is not yet connected to. + +36. **Multi-source verification:** Before accepting any protocol state + (epoch changes, validator set updates), a validator MUST receive + consistent information from at least f+1 independent sources. + +37. **Inbound connection limits:** Each validator MUST limit inbound + connections to max(3n, 256) total, with per-IP and per-subnet limits + of 8 and 32 respectively. This prevents a single adversary from + monopolising connection slots. + +**9.8 Rate Limiting** + +To prevent resource exhaustion attacks: + +- **Per-account rate limit:** A validator MUST process at most + R_account Tier 1 vote requests per account per second (recommended: + R_account = 10). Excess requests are queued up to Q_max + (recommended: 100) and then rejected with ERR_RATE_LIMITED. + +- **Per-connection rate limit:** A validator MUST process at most + R_connection messages per connection per second across all types + (recommended: R_connection = 1000). This prevents a single malicious + connection from overwhelming the validator. + +- **Global rate limit:** A validator MUST limit total incoming message + bandwidth to B_max bytes per second (recommended: B_max = the + validator's network capacity × 0.8, leaving 20% headroom for + outbound traffic). + +- **New account cost:** Creating a new account (first transition) + requires a proof-of-work puzzle with difficulty D_new (recommended: + D_new = 2²⁰, approximately 1 second of single-core computation). + This prevents mass account creation attacks without requiring an + economic cost in any specific currency. + +**9.9 Keepalive** + +Each connection MUST send a PING message at least every 30 seconds if no +other messages have been sent. The remote node MUST respond with PONG +within 5 seconds. If no PONG is received after 3 consecutive PINGs, the +connection MUST be closed and the peer marked as potentially +unreachable. + +PING/PONG messages carry no payload and are 5 bytes each (4 byte +length + 1 byte type). They serve dual purposes: keeping QUIC +connections alive through NAT/firewalls and detecting peer failures. + +**Document Control** + +**Revision History** + + ------------- ------------ --------------- ------------------------------- + **Version** **Date** **Author** **Description** + + 0.1.0 2026-03-09 MESH Foundation Initial draft. Completes + specification suite with + SPEC-004, 005, 009. + ------------- ------------ --------------- ------------------------------- + +**Additional References** + +- Babel, K. et al. (2023). Mysticeti: Reaching the Limits of Latency + with Uncertified DAGs. arXiv:2310.14821. + +- Jovanovic, P. et al. (2024). Mahi-Mahi: Low-Latency Asynchronous BFT + DAG-Based Consensus. arXiv:2410.08670. + +- Arun, B. et al. (2024). Shoal++: High Throughput DAG BFT Can Be Fast + and Robust. USENIX NSDI 2025. + +- Keidar, I. et al. (2021). All You Need is DAG. ACM PODC 2021 + (DAGRider). + +- Danezis, G. et al. (2022). Narwhal and Tusk: A DAG-based Mempool and + Efficient BFT Consensus. EuroSys 2022. + +- Spiegelman, A. et al. (2022). Bullshark: DAG BFT Protocols Made + Practical. ACM CCS 2022. + +- Fischer, M., Lynch, N., Paterson, M. (1985). Impossibility of + Distributed Consensus with One Faulty Process. JACM. + +- RFC 9000: QUIC: A UDP-Based Multiplexed and Secure Transport. IETF, + 2021. + +- RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3. + IETF, 2018. diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..f0b6443 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "1.85.0" +components = ["clippy", "rustfmt", "rust-analyzer"] +targets = ["x86_64-unknown-linux-gnu"]