pqthreshold — How to write the first code (module-by-module)
Status: formative specification
Audience: implementers
Read first: INDEX.md
Verify with: TOOLING.md
INDEX.md tells you what to read. API.md defines public types. This document tells you which files to create, in what order, and which spec section governs each file — so implementation proceeds without guesswork.
Rule: Do not start Phase N until Phase N docs are read and Phase N−1 tests pass dart run tool/verify.dart full.
lib/
pqthreshold.dart # Tier 1 public barrel
testing.dart # Tier 2 only (Phase 3+)
src/
params/
scheme_id.dart
threshold_params.dart
errors/
threshold_exception.dart
util/
secret_buffer.dart # Disposable wipe
serialization/
pqth_header.dart
pqth_codec.dart
sharing/ # Phase 2
scheme/
feldman/ # Phase 2
dkg/ # Phase 3
frost/ # Phase 4
dkg/ # Phase 3
transcript/ # Phase 3
signing/ # Phase 4
ceremony/ # Phase 5
test/
pqthreshold_test.dart # smoke (planning)
serialization/ # Phase 1
vectors/ # JSON — see TEST_VECTORS.md
sharing/ # Phase 2
dkg/ # Phase 3
signing/ # Phase 4
tool/
verify.dart
Only create directories when their phase starts — avoid empty modules.
| Rule | Source |
|---|---|
| Crypto from pqforge facades first | SCHEMES.md §4 |
| Structure from swissarmyknife | SWISSARMYKNIFE.md |
Internal Result; public throws ThresholdException |
API.md §5.1 |
1-based participantIndex |
PARAMS.md §4 |
| All bytes canonical per spec | SERIALIZATION.md, PROTOCOL_MESSAGES.md |
| No secrets in logs or transcripts | SECURITY.md §9 |
import 'package:pqforge/pqforge.dart'; // PqBytes, PqClassical, …
import 'package:swissarmyknife/swissarmyknife.dart';
// pointycastle: only via pqforge, comment why — SCHEMES §4Docs: PARAMS.md, SERIALIZATION.md §3–4.1, API.md §3.1–3.2, SWISSARMYKNIFE.md §3.1–3.4
- Enum
SchemeIdwithfrostEd25519V1ordinal 1 (PARAMS.md §2). SchemeId.fromOrdinal(int)→SerializationErrorif unknown.
- Immutable
ThresholdParamsper API.md §3.1. - Factory
ThresholdParams.tOfNuses swissarmyknifeValidator(PARAMS.md §6). toBytes/fromBytesper SERIALIZATION.md §4.1.
- Sealed hierarchy per API.md §5.
- Helper
throwFromResult(Result<T, ThresholdException> r)for barrel.
- Encode/decode 8-byte header (SERIALIZATION.md §3.1).
- Validate magic
PQTH,ver == 0x01.
CodecPipelinefor length-prefixed fields (SWISSARMYKNIFE.md §3.3).- Round-trip tests in
test/serialization/pqth_header_test.dart.
- Export
ThresholdParams,SchemeId,ThresholdExceptiontypes fromlib/pqthreshold.dartwhen ready.
-
dart run tool/verify.dart fullpasses - Params reject invalid
t/nper PARAMS.md §3.2 - Header round-trip tests pass
params validate/params export— TERMINAL.md §7inspect— PQTH header + ThresholdParams; wrapped JSON metadata (no unwrap)- Tests:
test/cli/pqthreshold_cli_test.dart - Version:
dart run tool/version/generate_version.dart(frompubspec.yaml)
Docs: PROTOCOL_MESSAGES.md §4, FROST_PROFILE.md §6, TEST_VECTORS.md §4.1
- Polynomial, commitments, verify equation (FROST_PROFILE.md §6.2).
split,verifyShare,reconstructper API.md §4.2.- Wire helpers for PROTOCOL_MESSAGES.md §4.1–4.3.
- Add
test/vectors/feldman/*.jsonper TEST_VECTORS.md. test/sharing/feldman_test.dart:t-1fails,tsucceeds.
-
dart run tool/verify.dart fullpasses -
VerifiableSecretSharing.split/verifyShare/reconstructper API.md §4.2 -
Share/PublicKeycodecs round-trip - Feldman vectors under
test/vectors/feldman/; regenerate viadart run tool/generate_feldman_vectors.dart
Docs: PROTOCOL_MESSAGES.md §3, CEREMONIES.md §5, SWISSARMYKNIFE.md §3.5
- States and events matching PROTOCOL_MESSAGES.md §3.1.
CeremonySessionimplementing API.md §4.1.StateMachinefrom swissarmyknife.
- SERIALIZATION.md §4.5.
lib/testing.dart:DkgSimulator(API.md §2).
-
dart run tool/verify.dart fullpasses -
CeremonySessionsplit / verify / finalize per API.md §4.1 -
Transcriptappend/seal/verify and wire codec - DKG vectors under
test/vectors/dkg/; regenerate viadart run tool/generate_dkg_vectors.dart
Docs: FROST_PROFILE.md, PROTOCOL_MESSAGES.md §5
- H1/H2/H3 with SHA-512 (FROST_PROFILE.md §5).
- Round1/Round2 message bytes.
- API.md §4.3; verify via
PqClassical.provider.ed25519Verify.
-
dart run tool/verify.dart fullpasses -
ThresholdSigner.signPartial/combine/verifyper API.md §4.3 -
PartialSignaturewire codec round-trip - FROST vectors under
test/vectors/frost/; regenerate viadart run tool/generate_frost_vectors.dart - Combined signatures verify via pqforge Ed25519 (challenge uses RFC 8032 FROST-Ed25519 H2)
Docs: CEREMONIES.md, SERIALIZATION.md §4.6
lib/src/ceremony/root_ceremony.dart, rotation helpers.ContinuityProofcodec.
-
dart run tool/verify.dart fullpasses -
RootCeremony,ThresholdSigningCeremony,RotationCeremonyper API.md §4.4 -
ContinuityProofwire codec round-trip - Example app C1 → C3 → C5 flow
See ROADMAP.md Phase 6 and TEST_VECTORS.md §4.
-
dart run tool/verify.dart fullpasses - All TEST_VECTORS.md §4 acceptance criteria (including serialization round-trips)
- REVIEW_CHECKLIST.md published for independent review
- CHANGELOG 1.0.0 and Tier 1 API freeze per API.md §7 (at tag time)
1.0.0 shipped. Independent cryptographic review on REVIEW_CHECKLIST.md remains recommended before high-assurance production.
Phases 1–6 (§4–§8) shipped core Tier 1 cryptography for SchemeId.frostEd25519V1. See ROADMAP.md Signature coverage for what is and is not in scope.
| Target | Section | Primary modules / deliverables |
|---|---|---|
| 0.7.0 | §11 | bin/ CLI: VSS, DKG, sign commands; C2/C4 ceremony helpers |
| 0.8.0 | §12 | packages/crypto_shared, distributed C3, share wrapping interop |
| 0.9.0 | §13 | Review gate only — no new crypto schemes |
| 1.0.0 | §9.1 | Tier 1 + PQTH freeze after sign-off |
Docs: TERMINAL.md §7–8, CEREMONIES.md C2/C4
| Command group | Maps to | Spec |
|---|---|---|
| `vss split | verify | reconstruct` |
dkg participant |
C1 | PROTOCOL_MESSAGES.md §3 |
| `sign-partial | sign-combine | sign-verify` |
ceremony run c5 (or rotate) |
C5 | SERIALIZATION.md §4.6 |
lib/src/ceremony/dealer_ceremony.dart— C2 orchestration wrapper overVerifiableSecretSharinglib/src/ceremony/recovery_ceremony.dart— C4 explicit reconstruct + audit hooks
- All TERMINAL.md §7 planned commands implemented or explicitly deferred with doc update
-
test/cli/covers sign round-trip (sign run→sign verifyexit 0) - GETTING_STARTED.md CLI table matches shipped binary
Docs: INTEGRATION.md, GETTING_STARTED.md §14
| Module | Purpose |
|---|---|
officer_signing_client.dart |
One officer: signPartial over relay (mirror DKG client) |
distributed_signing.dart |
Coordinator collects partials until t, combines |
share_wrapping.dart |
PQTH share ↔ pqforge PqWrappedKey bytes (custody alignment) |
- Relay-based C3 test (2-of-3) without
SigningSimulator - Serverpod example uses injectable relay (in-memory for tests, DB stub documented)
- C1 and C3 both runnable through
CeremonyMessageRelay(DKG already is) - Share wrap/unwrap documented and tested against pqforge custody format
-
packages/crypto_sharedtests in CI ortool/verify.dart
No new SchemeId or signature algorithms. Operator checklist only:
- REVIEW_CHECKLIST.md — published for independent review
- REVIEW_CHECKLIST.md — all boxes signed by reviewer (operator)
- RELEASE_CHECKLIST.md — security reviewer items (operator)
- Claim boundaries in README still match SECURITY.md §6
1.0.0 tagged per §9.1 (CHANGELOG, API freeze, pubspec).
| Version | Change |
|---|---|
| 2026-08-13 | Initial implementation guide |
| 2026-08-13 | Phases 7–10 marked complete; 1.0.0 release |