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:
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.
|
||||
Reference in New Issue
Block a user