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 <noreply@anthropic.com>
This commit is contained in:
19
.cargo/config.toml
Normal file
19
.cargo/config.toml
Normal file
@@ -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
|
||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
/target
|
||||||
|
Cargo.lock
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
.DS_Store
|
||||||
14
Cargo.toml
Normal file
14
Cargo.toml
Normal file
@@ -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"
|
||||||
19
LICENSE
Normal file
19
LICENSE
Normal file
@@ -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.
|
||||||
414
PROJECT_CONSTITUTION.md
Normal file
414
PROJECT_CONSTITUTION.md
Normal file
@@ -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<AssetID, Commitment>` 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<AccountState>
|
||||||
|
- [ ] `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 <pubkey> --amount <value> --asset <id>`.
|
||||||
|
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 <hash>` 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)
|
||||||
9
crates/mesh-crypto/Cargo.toml
Normal file
9
crates/mesh-crypto/Cargo.toml
Normal file
@@ -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" }
|
||||||
1
crates/mesh-crypto/src/lib.rs
Normal file
1
crates/mesh-crypto/src/lib.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// MESH Protocol — Cryptographic Primitives (SPEC-006, SPEC-007)
|
||||||
9
crates/mesh-network/Cargo.toml
Normal file
9
crates/mesh-network/Cargo.toml
Normal file
@@ -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" }
|
||||||
1
crates/mesh-network/src/lib.rs
Normal file
1
crates/mesh-network/src/lib.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// MESH Protocol — Network Transport (SPEC-009)
|
||||||
6
crates/mesh-types/Cargo.toml
Normal file
6
crates/mesh-types/Cargo.toml
Normal file
@@ -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"
|
||||||
1
crates/mesh-types/src/lib.rs
Normal file
1
crates/mesh-types/src/lib.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// MESH Protocol — Core Data Structures (SPEC-002)
|
||||||
11
crates/mesh-validator/Cargo.toml
Normal file
11
crates/mesh-validator/Cargo.toml
Normal file
@@ -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" }
|
||||||
1
crates/mesh-validator/src/lib.rs
Normal file
1
crates/mesh-validator/src/lib.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// MESH Protocol — Validator Node (SPEC-003)
|
||||||
11
crates/mesh-wallet/Cargo.toml
Normal file
11
crates/mesh-wallet/Cargo.toml
Normal file
@@ -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" }
|
||||||
1
crates/mesh-wallet/src/lib.rs
Normal file
1
crates/mesh-wallet/src/lib.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// MESH Protocol — CLI Wallet (SPEC-003 client side)
|
||||||
1160
docs/specs/MESH-Dev-Environment-Specification.md
Normal file
1160
docs/specs/MESH-Dev-Environment-Specification.md
Normal file
File diff suppressed because it is too large
Load Diff
622
docs/specs/MESH-MVP-Roadmap-Solo-Bootstrap.md
Normal file
622
docs/specs/MESH-MVP-Roadmap-Solo-Bootstrap.md
Normal file
@@ -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 \<pubkey\> \--amount
|
||||||
|
\<value\> \--asset \<id\>. 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 \<hash\>. 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.*
|
||||||
1505
docs/specs/MESH-Protocol-Specification-Suite-v0.1.0.md
Normal file
1505
docs/specs/MESH-Protocol-Specification-Suite-v0.1.0.md
Normal file
File diff suppressed because it is too large
Load Diff
633
docs/specs/MESH-Security-Addendum-v0.1.1.md
Normal file
633
docs/specs/MESH-Security-Addendum-v0.1.1.md
Normal file
@@ -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).
|
||||||
|
------------- ------------ --------------- -------------------------------
|
||||||
826
docs/specs/MESH-Specification-Addendum-SPEC-004-005-009.md
Normal file
826
docs/specs/MESH-Specification-Addendum-SPEC-004-005-009.md
Normal file
@@ -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\<Hash\>, // Hashes of blocks from round-1 (\>= 2f+1
|
||||||
|
required)
|
||||||
|
|
||||||
|
weak_refs: Vec\<Hash\>, // Hashes of blocks from earlier rounds
|
||||||
|
(optional)
|
||||||
|
|
||||||
|
settlements: Vec\<Transition\>, // 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\<u8\>, // 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.\<network\>.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.
|
||||||
4
rust-toolchain.toml
Normal file
4
rust-toolchain.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[toolchain]
|
||||||
|
channel = "1.85.0"
|
||||||
|
components = ["clippy", "rustfmt", "rust-analyzer"]
|
||||||
|
targets = ["x86_64-unknown-linux-gnu"]
|
||||||
Reference in New Issue
Block a user