Repository navigation
S0.6 tinycloud-threshold: durable share store (candidate persistence, positive-proof retirement) - #539
Merged
Conversation
…ositive-proof retirement; Details: TC-2221
…ony binding, state-before-unlink retirement; Details: TC-2221
…fork descendants, strict temp sweep, full parent fsync; Details: TC-2221
… ceremony to its pin; Details: TC-2221
…use install and activation, state mutates after write; Details: TC-2221
…s, persist live forks, bound+compact retirement with predecessors; state v3; Details: TC-2221 - open: chain tip that is also a retired digest freezes (P3-1) - erase_share_file: unlink names with nlink>1, refuse links/symlinks before zeroing (P3-2) - live second activated genesis persists the proof and freezes (P3-3) - state v3: retired carries predecessor; dead entries compact at the 65536 bound, over-bound refuses (P3-4) - model: save/restore around open-path damage, recover-and-continue refusals, member-drop, pin-share and proof-loss faults, read-only dir, byte-frozen outcome check, op accounting
… evidence cannot thaw the store; model resync reconciles rollback timelines; Details: TC-2221
…s assign after durable commit, wide seeded-harness ceremony ids, compact-bounded recovery retirement; Details: TC-2221
samgbafa
marked this pull request as ready for review
November 10, 2026 13:40
This was referenced Nov 10, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Linear: TC-2221 residual — node-side persistence of candidate shares and retirement of old shares. PR only: no merge, tag or release is requested, and no production crate depends on
tinycloud-threshold(the same unwired shape #525 shipped in).What changes
1.
CandidateShare::to_bytes/from_bytes(src/cert.rs). The one crate-API addition the durable store needs:version:u8=1 || transcript_hash:32 || index:u16 || scalar:32(67 bytes). Decode is canonical only — exact length, version 1, index 1..=16, scalar < r and non-zero. Encoding writes directly into the guarded output; the raw scalar and every read-back buffer travel insideZeroizing.KeyShare::bindre-verifies the reloaded scalar against the certificate's public share before use. This is a secret-export surface.2.
storemodule (src/store.rs). One member's file-volume share store for one network:share-<cert-digest>(the 67-byte candidate),proofs/<cert-digest>(signed certificate plus, once activated, the owner activation statement and receipts),dealt/<ceremony-id>markers, a versionedstaterecord, and an exclusivelockfile. Semantics:openholds an exclusive advisory lock for the store's lifetime; a second opener getsBusy.member(this node's DID) scopes every acceptance.proofs/— genesis included — is verified throughverify_activation(AllHolders) before it can extend the pin or count toward a fork; a flag alone is never trusted. A recordedstatepin must be a verified activated certificate (chain member or fork child); anything else isCorrupt.accept_ceremonyrequires the ceremony's anchor to match this store's owner/network, this member to be among its recipients, andcurrentto equal the pin.install_candidaterequires the ceremony id to have been accepted, then reads the persisted file back and re-binds it (and checks the index) before the candidate can receive a receipt.statebefore the file unlink, so a crash is always recovered as "erasure owed", never as a missing promised share. A receipt-bearing candidate whose share is still needed is the only missing-fileCorrupt; a candidate already retired by durable proof converges even when its share is gone.current_share), install, accept, and further recordings, across restarts.*.tmp-<pid>-<seq>, created withcreate_new+ 0600, and zeroed + unlinked on any failure;opensweeps leftovers. Parent directories are fsynced after hierarchy creation. Erasure is zero-overwrite + fsync + unlink + dir-fsync (best-effort; journal/CoW residue is documented).record_activationis idempotent per verified chain digest, so concurrent retirement converges.3. Certificate accessors (
src/cert.rs):CertificateBody::previous(),epoch(),rekey(). No behavior change.4. SPEC/README. "Implemented surface" bumped to S0.6; S0.6 appendix records the layout, formats, and rules above.
Tests (test-first)
Nineteen store tests plus the codec refusal table, including: unverified activation flag never trusted; second opener refused while the lock is held; foreign-anchor, member-excluding, and stale-pin ceremonies rejected with the candidate untouched; forked activation persisted before freeze and freeze survives restart; receipted candidate converges when its share is missing but the retirement proof is durable; leftover temp files swept; restart between every transition; concurrent retirement.
Not in this PR
Volume mount and backup exclusion, DB/peer pin sources, boot freshness (F1–F4), audit rows,
instance_idbinding, dstack/compose hardening — all node-runtime wiring, out of scope until the wiring decision.Verification run here
cargo test --locked -p tinycloud-threshold --releasewithPROPTEST_CASES=1024: 245/245 (see check results on this PR).cargo clippy --locked -p tinycloud-threshold --all-targets -- -D warningsandcargo fmt --all -- --check: clean.Cargo.toml,Cargo.lockuntouched).Notes for the crypto review
to_bytesis the secret-export surface: canonical 67-byte encoding, encode writes directly into theZeroizingoutput with a guarded raw-scalar intermediate; decode takes guarded fixed buffers;bindre-checks the scalar before any use.Provenance log
Sources consulted:
tinycloud-threshold/SPEC.md(§3.11–3.12); Linear TC-2221, TC-2224 (gate A design v5,/var/tmp/tc2092-gates/TC-2224-design-v5.md), TC-2226; the crate's own source and tests; PR #525's body as house format; Bobbie's security review of the first revision (P1/P2 findings, all addressed in the second revision). No dependency was added or changed. No TACo, nucypher, nucypher-core, ferveo, umbral or taco-web material was opened, fetched, cloned, searched, recalled or requested from a model.Details: TC-2221