Skip to content
Open
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
151 changes: 151 additions & 0 deletions solutions/LP-0016.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# 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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation PR: logos-blockchain/logos-execution-zone#465
This PR adds to the LEZ repo. Lamda prize submissions are expected to use the LEZ, not necessarily modify it.

Copy link
Copy Markdown
Author

@syafiqeil syafiqeil May 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback @jzaki! You're right. The initial submission incorrectly added code directly to the LEZ repo. I initially structured it within the LEZ workspace assuming that was the expected approach for SPEL-base programs.

I've since decoupled the project into a standalone repository (logos-anonymous-forum: https://github.com/syafiqeil/logos-anonymous-forum), which references LEZ as a git dependency rather than modifying it. The ## Repository section has been updated accordingly.

The standalone repo contains:

  • On-chain program (programs/membership_registry/) — SPEL framework guest program
  • Off-chain SDK (logos_moderation_sdk/) — forum-agnostic moderation library with FFI
  • ZK circuit (program_methods/guest/) — membership proof
  • demo.sh, membership_registry.idl.json, and CI workflow

The original LEZ PR (#465) is kept for reference but is no longer the primary implementation link.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain if this is/isn't a logos module? How can a user use this within Logos Basecamp, and via what qt ui plugin/module?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is a Logos module, split into two Basecamp modules following the core/UI architecture:

  • Core module (anonymous_forum_core (https://github.com/syafiqeil/anonymous_forum_core)): A C++ Qt plugin built with logos-module-builder. It wraps the Rust SDK (liblogos_moderation_sdk.so) via C-ABI FFI and exposes 12 Q_INVOKABLE methods (member, moderator, and aggregator operations) over Logos IPC (Qt RemoteObjects).
  • UI module (anonymous_forum_ui (https://github.com/syafiqeil/anonymous_forum_ui)): A QML interface built with mkLogosQmlModule providing three views: Register, Post, and Moderate.

To run within Basecamp:

cd anonymous_forum_ui
nix run --impure

This launches a standalone Basecamp app with both modules loaded, demonstrating the full moderation lifecycle.

Video demo of the Basecamp integration: https://youtu.be/_9RvF-oS7jM

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The metadata.json module configs are in their respective repos:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@syafiqeil Does the video have audio? I can't here anything. Please msg me on the discord, might be easier to cover some points on a call

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate the offer @jzaki. But as a non native english speaker (indonesian), I'm much more effective communicating in writing than speaking. I hope that's okay.

Apologies about the audio, if narration text is not enough, I'll check and fix that.

If there are specific points that need clarification or anything misaligned with lp-0016 requirements, I'm happy to address them in detail here. Please let me know what needs attention and I'll respond thoroughly.


- **Main Implementation (On-Chain + SDK):** https://github.com/syafiqeil/logos-anonymous-forum
- **Implementation PR:** https://github.com/logos-blockchain/logos-execution-zone/pull/465
- **Basecamp Core Module (C++ Qt Plugin):** https://github.com/syafiqeil/anonymous_forum_core
- **Basecamp UI Module (QML):** https://github.com/syafiqeil/anonymous_forum_ui

## Approach

### Architecture

The system is split into five components across three repositories:

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). The SDK is compiled to both WASM (for web) and a C-ABI shared library (`liblogos_moderation_sdk.so`) with a `cbindgen`-generated C header for native Basecamp integration.

4. **Basecamp core module** (`anonymous_forum_core/`) — A C++ Qt plugin built with `logos-module-builder` that wraps the Rust FFI layer as `Q_INVOKABLE` methods. Published via Qt RemoteObjects IPC, it exposes 12 methods (member, moderator, and aggregator operations) callable from any Logos Basecamp UI module.

5. **Basecamp UI module** (`anonymous_forum_ui/`) — A pure QML module built with `mkLogosQmlModule` providing three views: Register (member creation + aggregator setup), Post (anonymous message preparation), and Moderate (strike issuance + NSK reconstruction). All UI operations flow through `logos.callModule("anonymous_forum_core", ...)` via Logos IPC.

### 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:** Native Logos Basecamp application consisting of a C++ Qt core module (`anonymous_forum_core`) and a QML UI module (`anonymous_forum_ui`). The core module wraps the Rust SDK via C-ABI FFI (`liblogos_moderation_sdk.so`), and the UI communicates with it through `logos.callModule()` over Logos IPC (Qt RemoteObjects). Supports member registration, anonymous posting, moderator login, strike issuance, and NSK reconstruction — all running natively within the Logos Basecamp standalone app via `nix run --impure`.

- [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.md` in `logos-anonymous-forum` documents build instructions, program architecture, API usage, and step-by-step demo instructions.

- [x] **Reproducible demo:** `demo.sh` script and integration test suite. Build via `cargo build --release`. Test command: `./demo.sh`.

- [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.

- [x] **Native Basecamp module integration:** The forum operates as a first-class Logos Basecamp module: Rust SDK → C FFI (cbindgen) → C++ Qt plugin (logos-module-builder) → QML UI (mkLogosQmlModule). Verified end-to-end via standalone app with all method calls dispatched through Logos IPC.

## Supporting Materials

- **Video Demonstration (SDK + On-Chain):** https://youtu.be/Bj0GwITfYwM
- **Video Demonstration (Basecamp Integration):** https://youtu.be/_9RvF-oS7jM
- **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, while the C-ABI FFI layer (`liblogos_moderation_sdk.so` + `cbindgen` header) enables native integration with Logos Basecamp. The Basecamp app — built as a native C++ Qt core module and QML UI module — provides a visual interface for all core actions: member registration, anonymous posting, moderator login, strike issuance, and NSK reconstruction. The entire stack runs via `nix run --impure` with zero manual setup. 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 across three repositories with clear separation: `logos-anonymous-forum` contains the on-chain programs (`programs/membership_registry`), ZKVM binaries (`program_methods/guest`), and the off-chain Rust SDK (`logos_moderation_sdk` with FFI layer). `anonymous_forum_core` contains the C++ Qt plugin built with `logos-module-builder`. `anonymous_forum_ui` contains the QML interface built with `mkLogosQmlModule`. Formal protocol specification is provided in `docs/protocol.md`, including the Basecamp integration architecture (Section 5). Nix flakes are used for deterministic Basecamp module builds. The E2E integration test (with ZK proofs) runs within the LEZ workspace environment.

## Supporting Materials

- **Protocol specification:** `docs/protocol.md` — formal unlinkability proofs, retroactive deanonymization analysis, N-of-M trust model, two-tier collusion resistance, and Basecamp integration architecture (Section 5)
- **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.md` in `logos-anonymous-forum` — comprehensive build and usage instructions (covers all 3 repositories)
- **Basecamp module READMEs:** `anonymous_forum_core/README.md` and `anonymous_forum_ui/README.md` — API reference, build/run instructions, architecture diagrams

## Terms & Conditions

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