Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions solutions/LP-0016.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Solution: LP-0016 — Anonymous Forum with Threshold Moderation and Membership Revocation

**Submitted by:** Syafiq (Evice Labs)

## Summary

A privacy-preserving forum protocol built on the Logos Execution Zone (LEZ) where members post anonymously via ZK proofs, moderators issue strikes through N-of-M threshold consensus, and K accumulated strikes cryptographically reconstruct the offender's secret key — enabling on-chain slashing and retroactive deanonymization. The deliverable includes a forum-agnostic moderation library (standalone SDK) and a working Logos Basecamp app demonstrating the full lifecycle.

## Repository

- **Main Implementation (LEZ PR):** https://github.com/logos-blockchain/logos-execution-zone/pull/465
- **Frontend App (Basecamp):** https://github.com/syafiqeil/Logos-Anonymous-Forum-UI

## Approach

### Architecture

The system is split into three components with clear separation of concerns:

1. **On-chain program** (`programs/membership_registry/`) — A SPEL framework guest program compiled to RISC-V for the RISC Zero ZKVM. Exposes 4 instructions: `initialize_forum`, `register_member`, `verify_post`, and `slash_member`. Each forum instance is identified by a unique `forum_id`, enabling multiple independent instances with different parameters on the same deployment. State is stored in a PDA account derived from `["forum", forum_id]`.

2. **ZK membership proof circuit** (`program_methods/guest/src/bin/forum_membership_proof.rs`) — A standalone RISC Zero guest program that proves three properties in zero-knowledge: (a) the poster's commitment exists in the registry Merkle tree, (b) the commitment is not in the revocation list, and (c) the tracing tag was correctly derived from the poster's NSK. The proof reveals only the registry root, tracing tag, and message hash — never the poster's identity.

3. **Off-chain moderation library** (`logos_moderation_sdk/`) — A forum-agnostic SDK operating on abstract byte identifiers. Three clients handle the moderation lifecycle: `MemberClient` (post preparation with ECDH-encrypted Shamir shares), `ModeratorClient` (strike issuance with Schnorr-signed certificates), and `SlashAggregator` (two-tier Lagrange reconstruction of NSK). All clients are also exposed as WASM bindings for the Basecamp app.

### Key Design Decisions

**SPEL framework over raw NSSA.** Existing LEZ programs (token, AMM) use raw `read_nssa_inputs`/`ProgramOutput` because they predate SPEL. We chose SPEL's `#[lez_program]` and `#[instruction]` macros for declarative account constraints (PDA, signer, init, mut) and automatic IDL generation. This aligns with the evolving LEZ ecosystem direction. The alternative — manual NSSA boilerplate — was rejected because it provides no benefit while making the codebase harder to audit and maintain.

**Per-instance PDA via `forum_id`.** Initially we used a hardcoded PDA seed (`"forum_state"`), which limited deployment to one instance per program. We refactored to `pda = ["forum", forum_id]` so any number of independent forum instances can coexist under a single deployed program. The alternative — deploying separate program binaries per forum — was rejected as wasteful and operationally complex.

**Two-tier Shamir Secret Sharing.** The member's NSK is the root secret of a degree-(K-1) polynomial. Each post evaluates this polynomial at a unique x-coordinate, producing a per-post secret `s_post`. This `s_post` is then split into N-of-M Shamir shares (Tier 1) distributed to moderators. This two-tier design means an adversary must breach N moderators across K distinct posts — not just N moderators once.

**ECDH per-moderator encryption.** Each post generates an ephemeral secp256k1 keypair. Shares are encrypted using ECDH shared secrets between the ephemeral private key and each moderator's public key, with SHA-256 domain-separated key derivation. The alternative — broadcasting shares in plaintext — was rejected for obvious confidentiality reasons. Using a group encryption scheme was considered but rejected as unnecessarily complex for the N-of-M threshold already provided by Shamir.

**Per-member stake tracking.** The initial implementation used aggregate `total_staked`. We migrated to `member_stakes: Vec<([u8; 32], u64)>` to track exact per-member deposits, ensuring slash returns the precise staked amount rather than a hardcoded value.

### Why the Logos Stack

The Logos stack provides three properties essential for this protocol:

- **Trustless execution (LEZ):** The membership registry runs inside the RISC Zero ZKVM, ensuring that stake accounting, revocation, and slash verification are enforced by mathematical proof — not by trusting a server operator. A centralized alternative could selectively refuse to process slashes or modify stake balances.

- **Censorship-resistant state (Bedrock L1):** Finalized blocks on the L1 layer guarantee that once a slash transaction is included, it cannot be reverted or censored. A member who has accumulated K strikes cannot prevent their revocation by bribing or pressuring a centralized service.

- **Decentralized off-chain coordination:** Moderation certificates are exchanged off-chain without on-chain transaction costs for the common path (posting and moderating). On-chain interaction occurs only at the point of revocation — a single slash transaction. Building on a centralized messaging service would introduce a single point of censorship for moderation activity.

## Success Criteria Checklist

### Functionality

- [x] **Member registration with stake and anonymous posting:** `register_member` instruction registers a commitment to the Merkle tree and debits the member's balance. `forum_membership_proof` circuit generates a ZK proof of membership. Posts are unlinkable due to per-post random salt in `SHA256(NSK ∥ H(M) ∥ Salt)`.

- [x] **Retroactive linkability upon slash:** When NSK is exposed via slashing, any observer can recompute `SHA256(NSK_slashed ∥ H(M_i) ∥ Salt_i)` for every historical post and compare against published tracing tags. Documented in `docs/protocol.md` (Theorem 2).

- [x] **N-of-M moderation certificates:** `ModeratorClient.issue_strike()` produces Schnorr-signed certificates. `SlashAggregator.reconstruct_strike()` requires exactly N valid certificates — fewer are rejected with error `"The number of certificates has not yet reached the N-of-M moderator threshold."`.

- [x] **K strikes → slash transaction:** `SlashAggregator.reconstruct_nsk()` performs Lagrange interpolation over K strike points to recover the member's NSK. This NSK is submitted on-chain via `slash_member`, which is admin-only.

- [x] **Slashed commitment rejection:** The ZK circuit asserts `commitment ∉ revoked_commitments` via explicit byte comparison. Slashed members cannot generate valid proofs.

- [x] **Parameterisable K and N-of-M:** Set at `initialize_forum` time per forum instance. Different instances operate independently with different parameters.

- [x] **Forum-agnostic moderation library:** `logos_moderation_sdk` operates on `[u8; 32]` identifiers, makes no assumptions about content type, and exposes documented APIs for registration, proof generation, certificate construction, and slash submission.

- [x] **Working Basecamp app:** React application using WASM bindings (`WasmMemberClient`, `WasmModeratorClient`, `WasmSlashAggregator`). Supports forum creation, anonymous posting, N-of-M moderation voting, strike accumulation, and slashing — all through a browser UI without CLI interaction.

- [x] **Two forum instances with different parameters:** Supported via `forum_id`-parameterized PDA accounts. Demonstrated in deployment with different K and N-of-M values.

### Usability

- [x] **Library as importable SDK:** `logos_moderation_sdk` is a standalone Rust crate with `cdylib` and `rlib` targets. Any application can add it as a dependency without modification.

- [x] **IDL via SPEL framework:** Generated from `#[lez_program]` annotations. Shows 4 instructions, `ForumInstance` account type, and `MerkleTree` type definition.

### Reliability

- [x] **Proof failure handling:** `prepare_post()` increments `post_counter` only after all operations succeed, preventing nullifier consumption on error. ZK proof errors surface via `Result` types.

- [x] **Partial certificate rejection:** `SlashAggregator` enforces the N threshold client-side before reconstruction. Insufficient certificates return an explicit error.

- [x] **Transient failure handling:** The SDK design supports retry by separating post preparation (idempotent per counter value) from network submission. The Basecamp app queues operations client-side.

### Performance

- [x] **ZK proof generation:** ~98 seconds on Intel i7-6600U (2C/4T, 2015 Skylake). Expected <10 seconds on modern 8+ core hardware (Apple M-series, AMD Ryzen 7) due to RISC Zero's parallel proving architecture.

- [x] **CU cost documentation:** Registration and slash transactions execute in <30ms on the LEZ sequencer (observed: 26.5ms for deploy, 10.9ms for subsequent transactions). Exact CU counts visible in sequencer logs during deployment.

### Supportability

- [x] **Deployed on LEZ:** Programs deployed to local LEZ sequencer via `wallet deploy-program`. Block creation and transaction validation confirmed in sequencer logs.

- [x] **Integration tests:** `integration_tests/tests/forum.rs` covers the full lifecycle: initialization, registration, ZK proof generation, N-of-M moderation with 3 strikes, NSK reconstruction, and slashing with stake confiscation. Runs with both `RISC0_DEV_MODE=1` (1.3s) and `RISC0_DEV_MODE=0` (98s).

- [x] **README:** `README_LP0016.md` documents deployment steps, build instructions, program architecture, API usage, and step-by-step demo instructions.

- [x] **Reproducible demo:** `demo_e2e.sh` script and integration test suite. Build via `just build-artifacts` (Docker). Test command: `HOST_CC=gcc cargo test --release -p integration_tests -- test_forum_e2e_full_lifecycle --nocapture`.

- [x] **Video demo:** Narrated walkthrough covering architecture explanation, code highlights, IDL generation, E2E test with `RISC0_DEV_MODE=0` (real proofs), LEZ local deployment with bedrock/sequencer/indexer, and Basecamp app demonstration of the full moderation lifecycle.

## Supporting Materials

- **Video Demonstration:** https://youtu.be/Bj0GwITfYwM
- **Protocol Specification Document:** Found within the PR at `docs/protocol.md`.

## FURPS Self-Assessment

### Functionality

The program supports the complete anonymous forum lifecycle: forum creation with configurable parameters, member registration with stake, anonymous posting via ZK membership proofs, threshold moderation with N-of-M certificate construction, K-strike accumulation, on-chain slashing with stake confiscation, and post-revocation rejection. Each forum instance operates independently via unique `forum_id` identifiers. The `verify_post` instruction maintains tracing tag uniqueness to prevent replay attacks.

**Limitations:** The `member_stakes` field uses `Vec<([u8; 32], u64)>` which scales linearly. For production use with thousands of members, this should be migrated to a Merkle map or separate PDA accounts per member.

### Usability

The moderation library exposes three client types (`MemberClient`, `ModeratorClient`, `SlashAggregator`) with straightforward APIs. WASM bindings enable browser-based usage without Rust knowledge. The Basecamp app provides a visual interface for all core actions: identity generation, posting, moderating, and slashing. The IDL generated via SPEL allows any tooling built on the SPEL ecosystem to interact with the program.

### Reliability

Error handling follows Rust idioms with `Result` types throughout. The SDK enforces invariants client-side: duplicate registrations are rejected, partial certificates (< N) cannot be submitted, tracing tag replay is blocked, double-slashing returns an error, and invalid NSK submissions are caught before state mutation. Post counter increments are deferred until all cryptographic operations succeed.

### Performance

ZK proof generation is the primary bottleneck (~98s on i7-6600U). All other operations complete in milliseconds. On-chain transactions execute in <30ms on the LEZ sequencer. The moderation SDK operates entirely in-memory with no I/O overhead. WASM bindings add negligible overhead for browser usage.

### Supportability

The codebase is organized into clearly separated crates: `programs/membership_registry` (business logic), `program_methods/guest` (ZKVM binaries), `logos_moderation_sdk` (off-chain library), and `integration_tests` (E2E tests). Formal protocol specification is provided in `docs/protocol.md`. The build system uses `just` for task automation and Docker for reproducible guest binary compilation. All critical paths are covered by the integration test which runs in both dev mode and production mode.

## Supporting Materials

- **Protocol specification:** `docs/protocol.md` — formal unlinkability proofs, retroactive deanonymization analysis, N-of-M trust model, two-tier collusion resistance
- **Architecture audit:** Comparison of SPEL-based approach vs native NSSA programs
- **IDL:** Generated via `spel generate-idl` — 4 instructions, ForumInstance account type
- **Video demo:** Narrated architecture walkthrough + E2E test with RISC0_DEV_MODE=0 + LEZ deployment + Basecamp app demonstration
- **README:** `README_LP0016.md` — comprehensive build, deploy, and usage instructions

## Terms & Conditions

By submitting this solution, I confirm that I have read and agree to the [Terms & Conditions](../TERMS.md).