Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
b976a46
fix(tbtc/signer): implement multi-agent-review findings (D1, D2, P0-P2)
piotr-roslaniec Aug 18, 2026
7a45c14
docs(tbtc/signer): track follow-up work deferred from PR #4198
piotr-roslaniec Aug 18, 2026
90d99f4
feat(tbtc/signer): add per-record hash chain to state witness journal
piotr-roslaniec Aug 18, 2026
e8e0ca8
docs(tbtc/signer): add v2-to-v3 sign-store migration runbook
piotr-roslaniec Aug 18, 2026
525b15d
chore(tbtc/signer): drop dead identity result, add error redaction an…
piotr-roslaniec Aug 18, 2026
85ce599
fix(tbtc/signer): implement second multi-agent-review findings (F-01 …
piotr-roslaniec Aug 19, 2026
9908062
ci(tbtc/signer): refresh TLA tools checksum
piotr-roslaniec Aug 19, 2026
cf4606e
fix(tbtc-signer): address multi-agent review findings (P0/P1/P2/P3)
piotr-roslaniec Sep 8, 2026
7bee000
refactor(tbtc-signer): unify segment-publication path, thread chain c…
piotr-roslaniec Sep 8, 2026
21d6cf0
fix(tbtc-signer): restore O(1) writes and close read-path verificatio…
piotr-roslaniec Sep 8, 2026
d711022
docs(tbtc-signer): fix FOLLOWUP.md's stale compaction-recovery guard …
piotr-roslaniec Sep 8, 2026
03e5c37
fix(tbtc-signer): split front-door identity checks from data-bearing …
piotr-roslaniec Sep 9, 2026
c1d901f
test(tbtc-signer): add regression coverage for remaining full-verify …
piotr-roslaniec Sep 9, 2026
7b5bd20
docs(tbtc-signer): fix remaining doc drift from the identity()/read-p…
piotr-roslaniec Sep 9, 2026
6cd6c84
ci(tbtc-signer): fix clippy chunks_exact lint and refresh TLA jar che…
piotr-roslaniec Sep 9, 2026
94c5f29
test(tbtc-signer): fix flaky CI test isolation gap in provisioning FF…
piotr-roslaniec Sep 9, 2026
5530a96
test(tbtc-signer): fix second unguarded test that could wipe MAX_SESS…
piotr-roslaniec Sep 9, 2026
4bfb5fe
docs(tbtc-signer): remove completed FOLLOWUP.md tracking doc
piotr-roslaniec Sep 9, 2026
f1b02a5
refactor(tbtc-signer): remove 3 genuinely-unused items instead of all…
piotr-roslaniec Sep 9, 2026
3e624f0
Revert "refactor(tbtc-signer): remove 3 genuinely-unused items instea…
piotr-roslaniec Sep 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/tbtc/signer/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/tbtc/signer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ base64ct = { version = "1.8", features = ["alloc"] }
criterion = "0.5"
pretty_assertions = "1.4"
proptest = "1.6"
tempfile = "3"
53 changes: 38 additions & 15 deletions pkg/tbtc/signer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,36 @@ in `docs/rust-rewrite-bootstrap.md`.

## Current scope

- Exposes a C ABI (`libfrost_tbtc`) with coarse operations keyed by `session_id`:
- `RunDKG`
- `StartSignRound`
- `FinalizeSignRound`
- `BuildTaprootTx`
- `RefreshShares` (symbol retained in ABI 4.0, but fail-closed with
`cryptographic_refresh_not_supported` until a multi-round FROST refresh
protocol is implemented; metadata from the retired synthetic stub cannot
postpone cadence or establish key continuity, and an unanchored legacy
refresh-only session is immediately overdue)
- Exposes a C ABI (`libfrost_tbtc`) with a hybrid surface. The
`session_id`-keyed subset is:
- `BuildTaprootTx` (`frost_tbtc_build_taproot_tx`)
- `RefreshShares` (`frost_tbtc_refresh_shares`; symbol retained in
ABI 3, but fail-closed with `cryptographic_refresh_not_supported`
until a multi-round FROST refresh protocol is implemented;
metadata from the retired synthetic stub cannot postpone cadence
or establish key continuity, and an unanchored legacy refresh-only
session is immediately overdue)
- `VerifySignatureShare` (`frost_tbtc_verify_signature_share`)
- The hardened interactive signing session ops
(`InteractiveSessionOpen`, `InteractiveRound1`, `InteractiveRound2`,
`InteractiveSessionAbort`, `InteractiveAggregate`), all keyed by
`(session_id, attempt_id, member_identifier)` per the frozen Phase 7
interactive-session spec.
The round-level subset is NOT `session_id`-keyed and matches the
round-level calls keep-core's native FROST engine expects:
- `frost_tbtc_dkg_part1` / `_dkg_part2` / `_dkg_part3` take
`DkgPart{1,2,3}Request` shaped for a single round of DKG with no
`session_id`.
- `frost_tbtc_new_signing_package` takes
`NewSigningPackageRequest { message_hex, commitments }` with no
`session_id`.
The wire-contract version reported by `frost_tbtc_abi_version` is
`abi_major = 5, abi_minor = 0` (see `TBTC_SIGNER_ABI_MAJOR` /
`TBTC_SIGNER_ABI_MINOR` in `pkg/tbtc/signer/src/lib.rs`). Earlier
references to ABI 4.x are stale; this build reports ABI major 5
(bumped from 4 to reflect this PR's FFI symbol removals in addition to
the RefreshShares terminal-error semantics that originally justified
major 4).
- Exposes fine-grained interactive (member-custodied nonce) signing via:
- `InteractiveSessionOpen`
- `InteractiveRound1`
Expand Down Expand Up @@ -448,11 +468,14 @@ storage guarantees for that hardware-level failure boundary.
transient with the live nonce state, so restart requires a fresh Open.
ABI 3.2 adds the independent per-wallet heartbeat rate-limit config and
dedicated heartbeat policy-rejection metric.
- ABI 4.0 reserves `RefreshShares` as fail-closed until a real multi-round,
zero-constant FROST refresh protocol exists. Because valid refresh requests
now return terminal `cryptographic_refresh_not_supported` instead of a
synthetic success result, ABI-3 bridges must reject this library during
compatibility negotiation.
- At ABI 3, `RefreshShares` is reserved as fail-closed until a real
multi-round, zero-constant FROST refresh protocol exists. Refresh
requests return terminal `cryptographic_refresh_not_supported`
instead of a synthetic success result, so consumers must not rely
on `RefreshShares` for share continuity; persisted metadata from the
retired synthetic stub is non-authoritative for refresh cadence and
key continuity, and any plan that depends on it must be retargeted
at a future ABI bump rather than relied on under ABI 3.
- ABI-3 migration is intentionally fail closed. A pre-ABI-3 in-flight ROAST
session has no stored BIP-341 sighashes and must be abandoned and restarted
under a fresh `session_id`; its cached fingerprint cannot be upgraded in
Expand Down
24 changes: 15 additions & 9 deletions pkg/tbtc/signer/docs/rust-rewrite-bootstrap.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Rust Rewrite Bootstrap (tbtc-signer)

Date: 2026-02-23
Status: Partial — bootstrap landed, production gates open

This document tracks the initial code bootstrap for the `tbtc-signer` Rust
rewrite architecture.
Expand All @@ -20,15 +21,20 @@ rewrite architecture.
- Added `pkg/tbtc/signer` Rust crate that builds a `cdylib` named
`libfrost_tbtc`.
- Added a C ABI contract in `pkg/tbtc/signer/include/frost_tbtc.h`.
- Implemented coarse request/response operations keyed by `session_id`:
- `frost_tbtc_run_dkg`
- `frost_tbtc_start_sign_round`
- `frost_tbtc_finalize_sign_round`
- `frost_tbtc_build_taproot_tx`
- `frost_tbtc_refresh_shares` (symbol retained, but ABI 4.0 fails closed; the
one-shot request cannot perform cryptographic FROST share refresh, and the
major bump prevents ABI-3 consumers from accepting the changed response
semantics)
- Implements a hybrid C ABI surface (see `README.md` for the full inventory):
- `session_id`-keyed subset: `frost_tbtc_build_taproot_tx`,
`frost_tbtc_refresh_shares` (symbol retained, but ABI 3 fails closed
with `cryptographic_refresh_not_supported`; the one-shot request cannot
perform cryptographic FROST share refresh), `frost_tbtc_verify_signature_share`,
and the hardened interactive signing session ops
(`frost_tbtc_interactive_session_open`, `frost_tbtc_interactive_round1`,
`frost_tbtc_interactive_round2`, `frost_tbtc_interactive_session_abort`,
`frost_tbtc_interactive_aggregate`), all keyed by
`(session_id, attempt_id, member_identifier)`.
- Round-level subset (NOT `session_id`-keyed): `frost_tbtc_dkg_part1` /
`_dkg_part2` / `_dkg_part3` (single round of DKG, no `session_id`), and
`frost_tbtc_new_signing_package` (`NewSigningPackageRequest { message_hex,
commitments }`, no `session_id`).
- Implemented idempotency and conflict checks for retried operations under the
same session ID.
- Added file-backed persistent session-state adapter with atomic writes and
Expand Down
48 changes: 42 additions & 6 deletions pkg/tbtc/signer/docs/signer-api-contract-decision-brief.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Signer API Contract Decision Brief

Date: February 23, 2026
Status: Partially adopted — see corrected FFI-surface description below

Purpose: capture the API-contract direction before further implementation work.

Expand Down Expand Up @@ -30,7 +31,7 @@ interface.

(file: `pkg/frost/signing/native_frost_protocol_frost_native.go`)

### Rewrite plan and `tbtc-signer` use coarse session operations
### Rewrite plan and `tbtc-signer` actual FFI surface (corrected)

The rewrite plan defines:

Expand All @@ -42,11 +43,46 @@ The rewrite plan defines:

(plan tracked in `pkg/tbtc/signer/docs/rust-rewrite-bootstrap.md`)

The bootstrap Rust crate already exposes this coarse C ABI surface:

(file: `pkg/tbtc/signer/src/lib.rs`)

## Design Alternatives
The actual FFI surface in `pkg/tbtc/signer/src/lib.rs` is HYBRID and does not
uniformly key on `session_id`:

- DKG stays round-level:
- `frost_tbtc_dkg_part1` takes `DkgPart1Request { participant_identifier,
max_signers, min_signers }` (no `session_id`).
- `frost_tbtc_dkg_part2` takes `DkgPart2Request { secret_package_hex,
round1_packages }` (no `session_id`).
- `frost_tbtc_dkg_part3` takes `DkgPart3Request { secret_package_hex,
round1_packages, round2_packages }` (no `session_id`).
- Signing-package construction stays round-level:
- `frost_tbtc_new_signing_package` takes
`NewSigningPackageRequest { message_hex, commitments }` (no `session_id`).
- Session-keyed (`session_id` is part of the request):
- `frost_tbtc_build_taproot_tx` (`BuildTaprootTxRequest`).
- `frost_tbtc_refresh_shares` (`RefreshSharesRequest`; symbol retained but
fail-closed with `cryptographic_refresh_not_supported` until a
multi-round FROST refresh protocol is implemented).
- `frost_tbtc_verify_signature_share` (`VerifySignatureShareRequest`).
- The hardened interactive signing session ops
(`frost_tbtc_interactive_session_open`, `frost_tbtc_interactive_round1`,
`frost_tbtc_interactive_round2`, `frost_tbtc_interactive_session_abort`,
`frost_tbtc_interactive_aggregate`) - all keyed by
`(session_id, attempt_id, member_identifier)` per the frozen Phase 7
interactive-session spec.
- Wire-contract version: the `frost_tbtc_abi_version` export reports
`abi_major = 5, abi_minor = 0` (per `TBTC_SIGNER_ABI_MAJOR` /
`TBTC_SIGNER_ABI_MINOR` in `lib.rs`). Earlier references to ABI 4.x are
stale; this build reports ABI major 5 (bumped from 4 to reflect this
PR's FFI symbol removals in addition to the RefreshShares terminal-error
semantics that originally justified major 4).

The "already exposes RunDKG / StartSignRound / FinalizeSignRound" claim in
the earlier draft of this brief is therefore an oversimplification: the
round-level DKG and signing-package construction paths are still
round-level, and only the build-tx / refresh-shares / verify-share /
interactive-session subset is session-keyed. The recommendation in the
Recommendation section below still favors the coarse session shape as the
end-state, but the current surface is a hybrid that needs to be made
explicit before any further keep-core wiring.

### Round-Level API Compatibility

Expand Down
Loading
Loading