# 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)