Repository navigation
Conversation
…s; Details: TC-2220
…text check; Details: TC-2220
…numerate fault patterns; Details: TC-2220
…relay scenarios; Details: TC-2221
…ds; Details: TC-2221
… accepted-commitment answers; Details: TC-2221
This was referenced Oct 30, 2026
Merged
This branch has not been deployed
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.
Adds the S0.4 authorized redistribution to
tinycloud-threshold: reshare and refresh of the current master secret from the members of a verified certificate to an owner-authorized cohort, with a possibly different threshold and size, over owner-closed, member-signed rounds R1–R3. Includesreshare_verify_transcript, which recomputes the outcome from the raw signed round records. The master public key is unchanged; the output is a candidate for the successor certificate. The crate remains an unwired workspace member.Stacked on #492. Base:
skgbafa/tc-2220-threshold-dkgat82ab38cbbdb64005eff7d4c694c99fb12cb0ce4f. Head:45341d995a1f535483a2461385b20da25055d076.What it does
reshare_deal,reshare_start_receiverandreshare_verify_transcriptaccept only an owner-authorized ceremony of kind reshare or refresh whose current-certificate digest equals the suppliedVerifiedCertificate. Refresh additionally requires the same t, n and index→DID directory as the current certificate. A dealer'sKeySharemust carry the current key context. A recipient's ceremony key must match its directory entry. These checks precede any randomness, opening or emitted message.InsufficientQualifiedat every recipient and the verifier, and the current epoch stays in force.TH("TC-THRESHOLD-V1-RESHARE-START", authorized_ceremony_digest)fromreshare_initial_transcript, for both reshare and refresh.reshare_verify_transcriptbounds the whole transcript to 4 MiB before checking signatures, requires exactly three rounds and trusts no supplied outcome fields.ReshareDeal,ReshareComplaints). R3 is01 || count:u16 || [(recipient:u16 || value:32)]. No error variant, dependency or shared-file change.SPEC.mdgains the S0.4 redistribution appendix (layouts, rule order, selection, scope and lifecycle).README.mdis updated.vectors/v1/reshare.jsonholds five fixed-seed transcripts with recomputed outcomes or errors; a test regenerates and replays them byte for byte.Completion assumes the trusted owner relay of §3.0, which delivers every honest message, and at least t old dealers that pass the rules. With fewer, the ceremony refuses with
InsufficientQualified. This implementation does not provide reliable broadcast. Redistribution does not erase earlier shares: old shares remain valid for the old certificate until integration erases them, and old and new shares carry different key contexts.Commits
1b9bccdbtest: newsrc/reshare.rs(module doc and tests only), newsrc/reshare_relay.rs(test-only signed owner relay and scenarios), and a newcheckpoint_2of3_reshareappended tosrc/checkpoint.rs.6e5e9287build:lib.rsmodule, exports and test-module wiring.50160879feat: redistribution implementation insrc/reshare.rs.77ecc9c8docs: SPEC appendix and README.65e49139style: rustfmt onreshare.rs,reshare_relay.rsand the appended checkpoint test (whitespace, trailing commas and one closure brace pair).45341d99test: generatedvectors/v1/reshare.json.No test or fixture that existed before this PR is edited;
checkpoint.rsgains one new test function. No other module changes.Checks
These ran locally at
65e49139with the pinned 1.97.1 toolchain, isolated homes and target, two jobs and two test threads.45341d99adds only the generated vector file that these runs compared byte for byte.cargo test --locked -p tinycloud-threshold --release --no-run: ok.TC_THRESHOLD_REGEN_VECTORS=1 cargo test --locked -p tinycloud-threshold --release reshare_vectors_regenerate_byte_for_byte_and_replay: ok.PROPTEST_CASES=1024 cargo test --locked -p tinycloud-threshold --release: 166 passed, 0 failed.cargo test --locked -p tinycloud-threshold --release checkpoint_2of3 -- --nocapture: three checkpoints passed and printed their outcomes. They includecheckpoint_2of3_reshare, which runs a DKG genesis redistributed to 3-of-4 with one answered complaint, the successor certificate and binding, all four 3-member subsets deriving and unwrapping, old/new context refusal, and a refused redistribution below t valid dealers with the 3-of-4 epoch still usable.cargo clippy --locked -p tinycloud-threshold --all-targets -- -D warnings: ok.cargo fmt -p tinycloud-threshold -- --check: ok. The first run at77ecc9c8reported formatting differences, fixed in65e49139.cfg(test), ran the following:reshare_verify_transcriptagreed;CertificateBody::successor,verify_successorand binding;NotEnoughSharesfor two;ContextMismatchandMixedContextsfor an old share under the new context;InsufficientQualifiedat every recipient and the verifier when only two of three required dealers dealt, with the 3-of-4 epoch still unwrapping.The two enumeration tests run every behaviour assignment of the in-tree fault model: 2-of-3 → 2-of-3 under two seeds (96 ceremonies) and 3-of-5 → 3-of-4 (108 ceremonies). Every case keeps at least t valid dealers. They cover that model only.
Named tests:
genuine_2of3_to_3of4_preserves_the_master_key_and_binds_every_candidate,dkg_genesis_reshare_chain_keeps_the_master_key_through_refresh,old_shares_stay_in_their_own_context_after_redistribution,fewer_than_t_valid_dealers_abort_everywhere_and_the_old_epoch_stays_usable,within_the_secrecy_budget_but_below_t_valid_dealers_refuses_and_keeps_the_old_epoch,a_member_of_both_cohorts_signs_distinct_roles,t_prime_complainers_exclude_the_dealer_and_it_publishes_no_answer,false_complaint_is_refuted_by_a_valid_answer,one_recipient_bad_value_is_replaced_by_a_valid_answer,invalid_answer_excludes_the_dealer_and_the_next_dealer_is_selected,missing_r3_excludes_only_with_required_answers,malformed_r3_excludes_only_with_required_answers,invalid_unsolicited_answer_excludes_its_dealer,valid_unsolicited_answer_is_ignored,conflicting_r3_excludes_its_dealer,r3_naming_a_recipient_outside_the_new_cohort_is_malformed,malformed_r2_supplies_no_complaints,conflicting_r2_supplies_no_complaints_and_does_not_affect_the_same_nodes_dealer_role,duplicate_complaints_count_once,r2_naming_a_dealer_outside_the_old_cohort_supplies_no_complaints,relay_omitted_complaint_fails_only_the_affected_receiver,r1_public_checks_exclude_malformed_dealings_and_keep_the_master_key,missing_and_equivocated_r1_exclude,dealers_are_the_first_t_in_closed_round_order,wrong_cohort_r1_is_ignored_without_blame,wrong_cohort_r2_is_ignored_without_blame,wrong_cohort_r3_is_ignored_without_blame,dealing_refuses_unauthorized_contexts_before_any_randomness,receiver_start_checks_ceremony_index_and_recipient_key,forged_statement_fields_fail_owner_authentication,transitions_refuse_other_ceremonies_rounds_and_histories,retry_under_a_new_ceremony_cannot_reuse_an_earlier_dealing,verifier_recomputes_from_authenticated_records_only,transcript_bound_of_4_mib_precedes_verification,every_within_budget_fault_pattern_with_t_valid_dealers_agrees_2of3,every_within_budget_fault_pattern_with_t_valid_dealers_agrees_3of5_to_3of4,reshare_vectors_regenerate_byte_for_byte_and_replay,reshare_start_label_is_distinct_from_and_not_a_prefix_of_every_frozen_tag,initial_transcript_hashes_the_exact_ceremony_digest_for_reshare_and_refresh,answer_payload_has_the_exact_layout_and_rejects_noncanonical_bytes,redistribution_rounds_reuse_the_genesis_deal_and_complaint_layouts,random_answer_bytes_reject_or_reencode_canonically,structured_answer_mutations_reject_or_reencode_canonically,checkpoint_2of3_reshare.Clean room
Dependencies: no change (existing
blst,sha2,zeroize,subtle,rand_core,thiserror,hpke0.12 withx25519; developmented25519-dalek,proptest,rand_chacha,serde,serde_json,hex).Provenance log
Details: TC-2221
Update: follow-up at a429c48
One commit on
45341d99, changing onlysrc/reshare_relay.rs(tests) and one sentence ofSPEC.md. No production code, protocol, fixture, dependency or existing assertion changes.SPEC.md, S0.4 Scope: a selected dealer that can read other dealers' R1 before its own R1 is closed, acting with a new member, can choose a dealing that passes every check but makes a new public share the identity. Every recipient and the verifier then refuse withIdentityPointwithout attributing a dealer. This affects completion only, and the current epoch stays in force.agreed()asserts that each listed recipient finished successfully before reading its candidate.r2_naming_an_old_dealer_above_the_new_cohort_size_counts: from old 3-of-5 to new 3-of-4, a complaint naming dealer 5 counts against the old cohort size and is answered.different_signature_encoding_is_not_equivocation: a retransmitted R1, R2 or R3 that differs only in its signature encoding is the same message, so it causes no exclusion and drops no complaint.dealer_answers_only_for_its_accepted_commitments: a dealer whose accepted R1 carries other commitments than its own state, with one complaint below t′, publishes no answers and is excluded withMissingAnswer.Checks at
a429c480(pinned 1.97.1, isolated, two jobs and two test threads, private copy of the exact head):PROPTEST_CASES=1024 cargo test --locked -p tinycloud-threshold --release: 169 passed, 0 failed.checkpoint_2of3 -- --nocapture: three checkpoints passed.cargo clippy --locked -p tinycloud-threshold --all-targets -- -D warningsandcargo fmt -p tinycloud-threshold -- --check: ok.src/reshare.rs, made its named test fail at an assertion insrc/reshare_relay.rs; the file was restored to its original hash after each:different_signature_encoding_is_not_equivocationat the exclusion assertion;r2_naming_an_old_dealer_above_the_new_cohort_size_countsat the answer assertion;one_recipient_bad_value_is_replaced_by_a_valid_answerat the recipient-success assertion inagreed();dealer_answers_only_for_its_accepted_commitmentsat the empty-answer assertion.Details: TC-2221