diff --git a/Cargo.toml b/Cargo.toml index c46024b..9bfc136 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,5 @@ -# Standalone workspace — deliberately NOT a member of the repo-root -# workspace. This directory is designed to be extracted into its own -# repository (see PLAN.md §6) with `git mv` / `git filter-repo`; until -# then it builds independently against the repo's vendored sources -# (the root .cargo/config.toml source replacement applies here too). +# Standalone workspace. Current scope is README.md; PLAN.md is a frozen +# 2026-06 design note. This repository is already Bitcoin-PIR/attested-builder. [workspace] resolver = "2" diff --git a/PLAN.md b/PLAN.md index 2afdae9..a33eaa3 100644 --- a/PLAN.md +++ b/PLAN.md @@ -1,7 +1,15 @@ -# Attested Builder — Execution Plan +# Attested Builder — Execution Plan (frozen 2026-06-12) -Status: Phase 0 started 2026-06-12 (this directory). Owner decision log -at the bottom. +**Not current.** This file is the original design note (k-of-n Ed25519 +root bundles, Nitro/TDX, client strict mode). What the repo actually +produces, and what it deliberately does not, is in [README.md](README.md). + +Do not treat Phase 2–4 below as a backlog that means a backend is +unattested. Production trust is BuildEvidence v2 + SEV-SNP report-data +binding, consumed by BitcoinPIR pin tables. + +Status when written: Phase 0 started 2026-06-12. Owner decision log at +the bottom. ## Goal diff --git a/README.md b/README.md new file mode 100644 index 0000000..3cf4ec1 --- /dev/null +++ b/README.md @@ -0,0 +1,146 @@ +# Attested builder + +Standalone producer of BitcoinPIR production databases and build +evidence. It is not the serving runtime, not the browser verifier, and +not a multi-builder quorum service. + +The locked production commit is the one BitcoinPIR pins in +`PRODUCTION_ORAM_DB_PROOF_V2_PINS` and +`scripts/build_uki_attested_builder_tier3.sh`. Do not copy that hash +into this file. Operator steps that boot this code on VPSBG live in +BitcoinPIR: Flow H in `docs/PRODUCTION_OPERATIONS.md` and +`docs/ATTESTED_BUILDER_TIER3_UKI.md`. + +`PLAN.md` is a frozen 2026-06 design note (k-of-n Ed25519 bundles, +Nitro, client strict mode). It is not the current contract. + +## What one production run covers + +A production generation is one native full-build V2 pipeline: + +| Mode | Script | Input | +| --- | --- | --- | +| Snapshot | `scripts/build-snapshot-database.sh` | one Core `dumptxoutset` v2 file + `gettxoutsetinfo muhash` | +| Delta | `scripts/build-delta-database.sh` | two snapshot files + both MuHashes; set-diff is inside this process | + +The measured UKI only accepts: + +- `MODE=native-full-build-v2-snapshot` +- `MODE=native-full-build-v2-delta` +- `MODE=reattest-existing-v2` (proof-migration only; ineligible for + production TEE-ORAM) + +Native V2 forces `ROOTS_ONLY=0`, `STAGE_SERVER_DB=1`, `RUN_ONION_FFI=1`, +`BUILD_EVIDENCE_VERSION=2`. `latest/` is published only after the +runner sees V2, `evidence_mode=full_build`, and no predecessor hashes. + +From those inputs the same run emits every serving backend's bytes: + +| Backend | Artifacts | Bound in evidence | +| --- | --- | --- | +| DPF-PIR | `batch_pir_cuckoo.bin`, `chunk_pir_cuckoo.bin`, bucket Merkle | `bucket_super_root` | +| HarmonyPIR queries | same INDEX/CHUNK + bucket Merkle as DPF | same `bucket_super_root` | +| OnionPIR | packed entries, cuckoo, Merkle, FFI `onion_shared_ntt.bin` / `onion_index_all.bin` / sibling rows | `onion_super_root` + typed Onion v2 layout | +| Direct ORAM | `oram-direct-inputs/utxo_chunks_{index,}_nodust.bin` and `[direct_oram]` in `server-db/MANIFEST.toml` | server-db manifest hash | + +Plus the trust sidecars the BitcoinPIR runtime serves verbatim: + +- `server-db/` (server-loadable tree + `MANIFEST.toml`) +- `root-bundle-payload.bin` (v2 payload; scanner-verified Onion layout) +- `build-evidence.bin` / `build-evidence.report-data` +- `build-evidence.sev-snp-report.bin` when `EMIT_SEV_SNP_QUOTE=1` +- `database.manifest.sha256`, `all-artifacts.manifest.sha256` + +There is no separate “DPF builder” or “Onion builder”. A collection +assembled after the fact is not a production candidate. + +## What this repo does not cover + +These are out of scope here, not unfinished backends: + +| Concern | Where it actually lives | +| --- | --- | +| Harmony hint blobs | pir1 runtime hint pool; fingerprint-checked in the browser, not a DB-proof family | +| BHTM / trust-chain (`fromMuhash`, block hash) | `Bitcoin-PIR/bhtm` producer; BitcoinPIR `web/public/proofs/trust-chain/` | +| Serving pir1 binary pin | BitcoinPIR `PIR1_PIN` | +| Serving pir2 UKI measurement | BitcoinPIR `PIR2_TIER3_PIN` (runtime UKI, not this image) | +| Formal / EasyCrypt wire-shape | BitcoinPIR `verification/locks/formal-proofs.json` | +| Client k-of-n builder-key quorum | `PLAN.md` Phase 2; not shipped. Production clients pin evidence + builder binary/commit | +| Nitro / TDX guests | not implemented; SEV-SNP `/dev/sev-guest` is the only quote provider | +| Multi-builder diversity | not implemented | +| Development databases | BitcoinPIR `scripts/build_full.sh` / `tools/db-builder` — must not produce a production rotation | + +`BUILD_EVIDENCE_VERSION=1` and `ROOTS_ONLY=1` still exist as host/legacy +paths. They are not the production UKI contract. `reattest-existing-v2` +can re-bind already-built serving images and must report +`direct_oram_eligible=no`. + +The live BitcoinPIR `940611 -> 948454` lineage is a mixed-provenance +exception retained on that side. Do not rebuild it here to make the +history look uniform. + +## How BitcoinPIR consumes the output + +BitcoinPIR does not treat this repo as the live pin catalog. + +| Evidence | BitcoinPIR pin / lock | Who verifies | +| --- | --- | --- | +| V2 Onion layout + roots | `PRODUCTION_ONION_DB_PROOF_V2_PINS` | browser / WASM; local `db-proof verify` | +| V2 ORAM + producer identity | `PRODUCTION_ORAM_DB_PROOF_V2_PINS` + `verification/locks/generated-proofs.json` | same local v2 path; not `verify-live` | +| Builder SNP report | `web/public/proofs/oram-source/` | `pir-attested-builder verify-build-evidence` | +| DPF / Harmony roots | same V2 `bucket_super_root` | bound in this run's evidence; BitcoinPIR still *transports* them on the v1 opcode | + +`proof_dir` vs `proof_v2_dir` is a BitcoinPIR packaging split, not a +second producer. The production UKI emits one V2 sidecar set. It does +not emit a parallel `BUILD_EVIDENCE_VERSION=1` directory. Live DPF and +Harmony clients still fetch `REQ_GET_DB_PROOF` and pin +`PRODUCTION_DB_PROOF_PINS` (no `proofVersion`); that table currently +names the retained mixed-provenance v1 sidecars. A new height therefore +has attested DPF/Harmony *bytes* in the V2 evidence, but no UKI-produced +v1 sidecar for that opcode. Do not invent a second producer to close +that packaging gap, and do not pair a `server-db` from one run with +evidence from another. + +## Layout + +| Path | Role | +| --- | --- | +| `coremuhash/` | Bitcoin Core MuHash3072 | +| `utxosnapshot/` | Core v2 `dumptxoutset` parser + MuHash gate | +| `dbpipeline/` | Deterministic INDEX/CHUNK/Onion/Merkle stages | +| `onionffi/` | Optional C++ OnionPIR preprocess (`--features ffi`) | +| `rootbundle/` | Canonical payload + optional Ed25519 wrapper | +| `builder/` | `pir-attested-builder` CLI | +| `scripts/build-snapshot-database.sh` | Snapshot orchestration | +| `scripts/build-delta-database.sh` | Delta orchestration | +| `scripts/local-regtest-e2e.sh` | Committed-fixture smoke | +| `scripts/local-mainnet-build.sh` | Owner-host wrapper; not a production authorization | +| `fixtures/` | Golden parser/MuHash vectors | + +## Commands + +```bash +cargo test --workspace +scripts/local-regtest-e2e.sh +``` + +Inspect or verify a finished output: + +```bash +pir-attested-builder inspect-build-evidence OUT/build-evidence.bin +pir-attested-builder verify-build-evidence OUT/build-evidence.bin \ + --snapshot SNAPSHOT --builder-bin BIN \ + --payload OUT/root-bundle-payload.bin \ + --database-manifest OUT/database.manifest.sha256 \ + --all-artifacts-manifest OUT/all-artifacts.manifest.sha256 \ + --server-db-manifest OUT/server-db/MANIFEST.toml \ + --expected-muhash MUHASH \ + --expected-anchor-height HEIGHT \ + --sev-snp-report OUT/build-evidence.sev-snp-report.bin +``` + +`--expect-*` values come from the independently accepted generation +record, never from a live PIR server. + +Wire-format changes to `rootbundle` follow +`rootbundle/COMPATIBILITY.md`. diff --git a/coremuhash/src/lib.rs b/coremuhash/src/lib.rs index 8083934..f657a92 100644 --- a/coremuhash/src/lib.rs +++ b/coremuhash/src/lib.rs @@ -2,7 +2,7 @@ //! `gettxoutsetinfo muhash` (`src/crypto/muhash.{h,cpp}`), reimplemented //! bit-compatibly in Rust. //! -//! The attested builder (see ../PLAN.md) ingests a `dumptxoutset` +//! The attested builder (see ../README.md) ingests a `dumptxoutset` //! snapshot, recomputes this hash over every coin, and refuses to build //! the PIR database unless it matches the muhash pinned for the chain //! anchor. Bit-compatibility with Core is the entire point: the pinned diff --git a/fixtures/README.md b/fixtures/README.md index 6e92969..18ea8d0 100644 --- a/fixtures/README.md +++ b/fixtures/README.md @@ -1,9 +1,13 @@ # attested-builder fixtures -Golden data for Phase 1 (`utxosnapshot` parser + muhash verification). -Produced 2026-06-12 against the owner's Bitcoin node. All values below -are exact strings copied from `bitcoin-cli` output — the end-to-end -golden test must reproduce the muhash **display hex** byte-for-byte. +Golden data for `utxosnapshot` parser + muhash verification. Produced +2026-06-12 against the owner's Bitcoin node. All values below are exact +strings copied from `bitcoin-cli` output — the end-to-end golden test +must reproduce the muhash **display hex** byte-for-byte. + +Current producer scope is the repo [README](../README.md). Live +BitcoinPIR pins stay in that repository's `web/src/attest-pin.ts`; the +mainnet tables below are snapshot metadata, not a pin catalog. Core version for both fixtures: **Bitcoin Core v31.0.0** (`getnetworkinfo` version `310000`, subversion `/Satoshi:31.0.0/`; @@ -66,8 +70,7 @@ case 1 (p2sh), and the raw-script fallback (p2wpkh, p2tr), plus amount compression across many magnitudes and VARINT heights/coinbase flags. NOT covered: P2PK cases 2–5 (no P2PK outputs here) — the `utxosnapshot` unit tests should take those from Core's -`compress_tests.cpp` vectors as PLAN.md Phase 1 step 1 already calls -for. +`compress_tests.cpp` vectors. Note: the fixture is **recipe-reproducible, not byte-reproducible** — wallet keys, txids and the muhash differ on every regeneration. The @@ -75,10 +78,11 @@ committed `.dat` + the strings above are the canonical golden pair. --- -## 2. Mainnet production snapshots (metadata only — files stay on SSD) +## 2. Mainnet snapshots captured 2026-06 (metadata only — files stay on SSD) -These are the full and delta anchors used by the deployed production -databases: +These are the `940611` / `948454` Core snapshot records used by the +retained BitcoinPIR lineage. They are not an instruction to rebuild +that lineage. - full snapshot: height `948454` - delta snapshot range: `940611 -> 948454` @@ -156,7 +160,7 @@ plus/minus delta -> Merkle roots/root bundle". --- -## 3. gen_1_onion dust/whale counts (PLAN.md node-task 4) +## 3. gen_1_onion dust/whale counts (historical sizing, 2026-06-12) Re-run 2026-06-12 with `gen_1_onion --data-dir ` (binary from this branch; OnionPIR entry size 3328 B, 4 partitions) against diff --git a/rootbundle/Cargo.toml b/rootbundle/Cargo.toml index 9608eaa..5e89fc3 100644 --- a/rootbundle/Cargo.toml +++ b/rootbundle/Cargo.toml @@ -3,7 +3,7 @@ name = "rootbundle" version = "0.1.0" edition.workspace = true license.workspace = true -description = "Canonical signed root bundle: binds PIR database Merkle roots to a chain anchor + muhash, with k-of-n Ed25519 verification" +description = "Canonical root-bundle payload: binds PIR Merkle roots to a chain anchor + muhash (optional Ed25519 wrapper)" publish = false [dependencies] diff --git a/rootbundle/src/lib.rs b/rootbundle/src/lib.rs index 361f44c..f9320a9 100644 --- a/rootbundle/src/lib.rs +++ b/rootbundle/src/lib.rs @@ -1,13 +1,13 @@ //! Canonical signed root bundle. //! -//! The bundle is the single client-facing trust artifact of the attested -//! builder design (see ../PLAN.md): it binds the PIR database Merkle -//! roots to a chain anchor (block hash + height), the Bitcoin Core -//! `muhash` of the UTXO set the database was built from, and every -//! build parameter that affects the output bytes. Builders (plain -//! hosts, Nitro enclaves, SEV guests) each sign the identical canonical -//! payload; clients accept a database root iff at least `threshold` -//! signatures from distinct pinned builder keys verify. +//! Canonical payload that binds PIR Merkle roots to a chain anchor, +//! the Bitcoin Core `muhash` of the source UTXO set, and every +//! build parameter that affects output bytes. +//! +//! Production trust is BuildEvidence v2 plus an optional SEV-SNP +//! report (see the repo README). The Ed25519 k-of-n wrapper remains +//! available; BitcoinPIR clients pin evidence hashes rather than a +//! builder-key quorum. The 2026-06 design note is PLAN.md. //! //! Encoding follows the same hand-rolled, length-prefixed, canonical //! style as `pir-identity` (no serde): one and only one byte string per diff --git a/scripts/local-regtest-e2e.sh b/scripts/local-regtest-e2e.sh index aa81412..a92629d 100755 --- a/scripts/local-regtest-e2e.sh +++ b/scripts/local-regtest-e2e.sh @@ -1,10 +1,10 @@ #!/usr/bin/env bash # Deterministic local end-to-end smoke for the tiny committed regtest fixture. # -# This is intentionally a plain-host test. It exercises the same trust chain -# the TEE builder must run later: -# snapshot -> muhash gate -> flat UTXO set -> deterministic DB artifacts -# -> root bundle payload -> fixed-key signature -> quorum verify -> receipt. +# This is intentionally a plain-host smoke. It exercises the same +# snapshot -> muhash gate -> deterministic DB artifacts -> root payload +# chain as a native full-build, then a test-only Ed25519 wrap. Production +# TEE trust is BuildEvidence v2 + SEV-SNP, not this test key. set -euo pipefail