diff --git a/solutions/LP-0017.md b/solutions/LP-0017.md new file mode 100644 index 0000000..2caa4bd --- /dev/null +++ b/solutions/LP-0017.md @@ -0,0 +1,141 @@ +# Solution: LP-0017 — Whistleblower + +**Submitted by:** Thompsonmina + +## Summary + +Whistleblower is a Logos Basecamp app for censorship-resistant document +publication. A user picks a file, attaches metadata, and submits; the +app uploads to Logos Storage, gets back a content identifier (CID), +broadcasts the CID + metadata over Logos Delivery, and either the +publisher or any permissionless third party anchors the CID on-chain via +the `chronicle-registry` SPEL program on LEZ. + +The submission includes `logos-chronicle`, a standalone reusable +document-indexing module any Basecamp app can depend on, and +`batch-anchor`, a permissionless CLI that subscribes to the Chronicle +Delivery topic and batch-anchors accumulated CIDs (up to 50 per tx) +without coordination with the original publisher. + +## Repository + +- **Repo:** https://github.com/Thompsonmina/WhistleBlower-Logos- +- **Demo video:** https://github.com/Thompsonmina/WhistleBlower-Logos-/releases/download/demo-v1/demo.mp4 + +## Approach + +The pipeline splits cleanly into a **publish path** and an **anchor +path**, with one shared on-chain registry. + +**Publish path — `logos-chronicle` (Basecamp module).** A Logos Core +module in C++/Qt exposing JSON-in / JSON-out methods. `publishFileJson` +chains: (1) upload to Logos Storage with exponential-backoff retries, +(2) build + sign a metadata envelope (`cid`, `title`, `description`, +`content_type`, `size_bytes`, `timestamp`, optional `tags`, +deterministic `metadata_hash`), (3) broadcast on the Chronicle Waku +topic `/chronicle/1/document-index/json`. Re-broadcasting the same CID +is deduped locally. Optional `anchorBatchJson` / +`anchorStatusJson` / `lookupAnchorJson` for publisher-initiated +on-chain anchoring, wired via a generated FFI cdylib. + +**Anchor path — `chronicle-registry` (SPEL program) + `batch-anchor` +(CLI).** The registry is a permissionless PDA at +`[program_id, "registry"]` holding a Borsh `HashMap`. +Two instructions: `init_registry(anchorer)` and +`index_batch(anchorer, cids, metadata_hashes, anchor_timestamps)` up to +`MAX_BATCH = 50`. Idempotency is in-program (`contains_key`), which is +what lets the permissionless `batch-anchor` CLI replay any batch after +a restart without coordination. + +`batch-anchor` is a tokio daemon that seeds an in-memory dedup set from +on-chain state at startup, catches up over Waku's store protocol for +messages broadcast while it was offline, subscribes to the live relay, +and flushes the buffer on either size (50) or time (30 s) — whichever +comes first. + +**Why LEZ over zone-SDK.** The zone-SDK path "requires a single designated actor to perform consensus +inscription" concentrating anchor authority and undermining +the censorship-resistance premise of the problem. A SPEL program on LEZ is +permissionless — anyone with a wallet can submit `index_batch`, which +is exactly the property the `batch-anchor` CLI relies on. SPEL also +ships IDL generation, scaffolding, an auto-generated CLI, and the +`#[lez_program]` macro — strictly less code than rolling the inscription +format by hand. + +## Success Criteria Checklist + +- [x] **Upload**: app uploads to Logos Storage and obtains a CID (chronicle module, `publishFileJson`). +- [x] **Broadcast**: chronicle publishes a versioned metadata envelope on `/chronicle/1/document-index/json` immediately after upload. +- [x] **On-chain anchoring (UI)**: chronicle exposes `anchorBatchJson` / `anchorStatusJson` / `lookupAnchorJson`; whistleblower UI wires a per-row "anchor" button. +- [x] **Batch anchor tool**: `batch-anchor` CLI subscribes to the topic, batches up to 50 CIDs per tx, permissionless, idempotent (in-program `contains_key` + on-chain dedup seed at startup). +- [x] **On-chain registry**: `chronicle-registry` SPEL program on LEZ stores `(CID, metadata_hash, anchor_timestamp)` keyed on CID; queryable via `batch-anchor lookup `; ≥10 CIDs per tx (50). +- [x] **Document-indexing module**: `logos-chronicle` is a standalone Logos Core module with documented JSON API; any Basecamp app can depend on it. +- [x] **Basecamp app GUI**: `logos-whistleblower` builds via the repo's nix flake and loads into Basecamp. +- [x] **Module SDK README**: `logos-chronicle/README.md` + `logos-chronicle/docs/api.md`. +- [x] **IDL for LEZ program**: `chronicle-registry-idl.json` at repo root; regenerated via `make idl`. +- [x] **Upload retries with exponential backoff**: chronicle storage layer, documented in `logos-chronicle/docs/api.md`. +- [x] **Broadcast dedup**: chronicle keeps a per-CID publish ledger; subscribers (incl. `batch-anchor`) skip duplicates. +- [x] **Batch tool resume after interruption**: seeded from chain at startup + Waku store-protocol catch-up over a configurable lookback window. +- [x] **CU benchmarks (1 + 50 CID)**: documented in `README_CHRONICLE_REGISTRY.md` § Compute units (cold n=1 = 2,240 cycles; cold n=50 = 178,646 cycles). +- [x] **Local LEZ deployment**: chronicle-registry deploys to a local LEZ devnet via `make deploy`; `scripts/setup.sh` does so end-to-end. +- [ ] **E2E integration tests in CI**: IT contract sketched in `integration-test.toml`; chronicle smoke test on the IT topic; that runs against a real local sequencer; `RISC0_DEV_MODE` left unset so the prover runs in production mode CI runner that runs lez and logoscore environment pending. +- [x] **Top-level README** with build, addresses, app, tool, query: `whistleblower/README.md`. +- [x] **Reproducible E2E demo script**: `scripts/run-app.sh` + . +- [x] **Narrated video demo**: linked above;. +- [x] **Dual licensed MIT + Apache-2.0**: `LICENSE-MIT`, `LICENSE-APACHE`. + +## FURPS Self-Assessment + +### Functionality + +Upload → broadcast → optional publisher anchor → batch anchor → on-chain +lookup, end-to-end. Two independent anchor consumers +(`chronicle::anchorBatchJson` for publisher-initiated, `batch-anchor` +for permissionless third-party) sharing one registry program. Borsh +serialisation gives deterministic on-chain bytes (required for risc0 +proof determinism). Idempotency is enforced in-program so callers can +replay batches freely. + +### Usability + +- Whistleblower Basecamp app: file picker + metadata fields + submit; per-row "anchor on-chain" action. +- One-shot evaluator path: `git clone && cd whistleblower && ./scripts/run-app.sh`. Idempotent. +- `logos-chronicle` module: JSON-in / JSON-out methods; SDK README + `docs/api.md`. +- IDL JSON for the LEZ program shipped at repo root. + +### Reliability + +- Upload: exponential-backoff retry on transient storage failures, structured error after exhaust. +- Broadcast: chronicle keeps a per-CID publish ledger so re-broadcasts are silent no-ops to subscribers. +- Batch anchor: dedup set seeded from on-chain state on every startup (no local-state drift); Waku store-protocol catch-up recovers messages broadcast while the anchor was offline. + +### Performance + +LP-17 R8 — CU costs instrumented via `risc0_zkvm::guest::env::cycle_count()` around each instruction body, logged to sequencer stdout. + +| Instruction | n | Cycles | Cycles / CID | +|------------------|----|---------|--------------| +| `init_registry` | — | 414 | — | +| `index_batch` | 1 | 2,240 | 2,240 | +| `index_batch` | 50 | 178,646 | 3,573 | + +Worst-case (n=50 near the 100 KiB account-data cap) is ~288k cycles — well under 1 Mi, ~3 % of the NSSA 32 Mi per-tx budget. + +### Supportability + +- Top-level + per-component READMEs, with an LP-17 requirement → file map. +- `scripts/setup.sh` (idempotent bootstrap) and `scripts/run-app.sh` (one-shot launcher). +- Project-local `--user-dir` for basecamp means re-runs never touch the user's regular `~/.local/share/Logos`. +- Pending: CI config + automated E2E test in CI. + +## Supporting Materials + +- Top-level README: https://github.com/Thompsonmina/WhistleBlower-Logos-/blob/master/README.md +- Chronicle-registry deep-dive: https://github.com/Thompsonmina/WhistleBlower-Logos-/blob/master/README_CHRONICLE_REGISTRY.md +- Chronicle module API: https://github.com/Thompsonmina/WhistleBlower-Logos-/blob/master/logos-chronicle/docs/api.md +- Demo script (off-camera reading copy): https://github.com/Thompsonmina/WhistleBlower-Logos-/blob/master/docs/demo-script.md +- Demo video: https://github.com/Thompsonmina/WhistleBlower-Logos-/releases/download/demo-v1/demo.mp4 + +## Terms & Conditions + +By submitting this solution, I confirm that I have read and agree to the [Terms & Conditions](../TERMS.md).