feat(node): store-melt P2P propagation — verify-then-delete + convergent epidemic (#1316) - #148
feat(node): store-melt P2P propagation — verify-then-delete + convergent epidemic (#1316)#148MichaelTaylor3d wants to merge 3 commits into
Conversation
First red stub for store-melt P2P propagation: the pure decide_melt gate (only a held, on-chain-confirmed melt deletes) and the set-once TombstoneSet that bounds each node to one broadcast per store. The 8 adversarial actuator tests + the receive/holder wiring follow. Refs #1316 Co-Authored-By: Claude <noreply@anthropic.com>
Piece #3 (receiver) + #4 (holder) of store-melt propagation, over spy-testable seams (MeltChain/MeltCache/MeltBroadcast) with the fail-closed NC-9 gate: only a held, on-chain-confirmed melt deletes; Err/Unknown never deletes; held-check precedes any chain read; the TombstoneSet CAS bounds each node to one rebroadcast so the epidemic terminates. All 8 adversarial tests green. Refs #1316 Co-Authored-By: Claude <noreply@anthropic.com>
…PEC (#1316) Spawn the store-melt receive ingest (opcode 221) beside holdings ingest off a second inbound receiver, and a holder watch loop that deletes + announces this node's own on-chain-melted stores — both sharing one tombstone. Bump workspace 0.75.6 -> 0.76.0 (feat/minor) + Cargo.lock. SPEC.md §14.5 documents the receive->verify->delete->rebroadcast contract, the NC-9 fail-closed gate, and the §5.4 public-broadcast exemption. Refs #1316 Co-Authored-By: Claude <noreply@anthropic.com>
🔴 Review gate: CHANGES-REQUIRED — the melt signal is unsound (do not merge)The production
Sound as-is (keep on re-spin): Required fix (direction): the Awaiting the loop-security + adversarial gates, then this re-spins with a proper melt-detection primitive and re-runs all three gates. The green CI + green unit tests are not sufficient assurance for an irreversible network-triggered delete. Generated by Claude Code |
Triple gate: all three independently blocked — re-implementing the melt signal (converting to draft)Three fresh, independent adversarial contexts reached the same verdict:
Unanimous root cause: the production
Sound and unchanged on the re-spin (all three cleared these): Required fix: the melt gate must key on a melt-SPECIFIC positive confirmation — the singleton lineage terminated in an owner-authorized melt spend (launcher spent + terminal child yielding no datastore output) — NOT This is the triple gate doing exactly its job: green CI and green unit tests were not assurance for a network-triggered irreversible delete. Generated by Claude Code |
What changed
Implements the dig-node legs of DIG-Network/dig_ecosystem#1316 (design locked in that issue; the dig-gossip
STORE_MELTED=221wire piece already merged). Melting a store now propagates the deletion across the P2P network so peers stop hosting a melted store's content — on-chain-verified and convergent..diggenerations (via the auditedcache_remove_cached), broadcasts a signedStoreMeltedAnnounce, and tombstones the store.inbound_receiver()— held-check first (O(1), before any chain call) → NC-9 on-chain verify → delete-if-melted → rebroadcast exactly once via a per-store tombstone CAS. Never-held / already-tombstoned ⇒ ignored, no re-storm.crates/dig-node-core/src/seams/dig_peer/store_melted.rs(puredecide_meltgate +TombstoneSet+ seams + loops + 10 tests);peer.rs::bring_up_dhtspawns the two loops sharing oneTombstoneSet;SPEC.md §14.5. Purely additive — no existing signature/struct changed.Security model
NC-9 (verify gates delete) — fail-CLOSED:
confirm_meltmapsOk(None)⇒Melted / Ok(Some)⇒Live (never delete) / Err⇒Unknown (never delete). The held-check precedes every chain call (a store is only verified if the node holds it — this bounds verify-cost DoS and anchors theOk(None)semantics). Signature is attribution-only, never the delete gate. §5.4-exempt (public all-peers broadcast, signed+mTLS, not recipient-sealed). §5.1-clean (deletes cached.dig; the on-chain anchor is permanent).ChainSource::resolve_singleton_lineage, which does not exist onb04dd41. The implementer usedAnchoredRootResolver::anchored_root(&store_id) -> Result<Option<Bytes32>, String>(the existing chain-watch authority) withOk(None)⇒Melted. The decider explicitly warned against treating a bareanchored_root()==Ok(None)as melt (it may be transient — "no confirmed generation yet" — rather than "singleton closed"), which if true would false-positive into wrongful deletion of a live store. The 8 tests use a spy chain, so they do not prove the realanchored_rootOk(None)semantics equal "melted." This must be verified before merge.melt_heightis a0advisory placeholder (receivers verify on-chain, never trust it) — follow-up.Verification
All 8 adversarial tests + 2 core green (
cargo test -p dig-node-core --lib store_melted→ 10 passed): live-store-never-deleted, chain-error-fail-closed, genuine-melt-deletes-all-and-rebroadcasts-once, never-held-skips-chain, already-tombstoned-inert, unheld-flood-no-chain-reads, convergence-terminates-at-holder-count, holder-tick-fail-closed-on-transient-error.cargo fmt --check→ 0 ·cargo clippy -p dig-node-core --all-targets --all-features -- -D warnings→ 0 · fullcargo test -p dig-node-core→ 527 passed (the only 9 failures are the known #1961 local-only port-bind env tests).Version
feat(new capability, backwards-compatible) →[workspace.package].version0.75.6 → 0.76.0. Cross-repo coherence (SYSTEM.md, canonical, normative-contract NC-9, docs.dig.net) is the orchestrator's to commit on land.Generated by Claude Code