Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 13 additions & 2 deletions pkg/tbtc/signer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ in `docs/rust-rewrite-bootstrap.md`.
- `StartSignRound`
- `FinalizeSignRound`
- `BuildTaprootTx`
- `RefreshShares`
- `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 fine-grained interactive (member-custodied nonce) signing via:
- `InteractiveSessionOpen`
- `InteractiveRound1`
Expand Down Expand Up @@ -361,7 +365,9 @@ storage guarantees for that hardware-level failure boundary.
`{"code":"...","message":"...","recovery_class":"..."}` JSON in `buffer`.
- `recovery_class` values:
- `recoverable`: caller can retry with corrected/updated input.
- `terminal`: session state is terminal for the current operation/session.
- `terminal`: the current operation/session cannot succeed in this runtime;
retry only after changing runtime capability or starting the documented
replacement flow.
- `frost_tbtc_roast_liveness_policy` response:
- `coordinator_timeout_ms`: effective coordinator-timeout policy in
milliseconds.
Expand Down Expand Up @@ -442,6 +448,11 @@ 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.
- 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
11 changes: 8 additions & 3 deletions pkg/tbtc/signer/docs/rust-rewrite-bootstrap.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ rewrite architecture.
- `frost_tbtc_start_sign_round`
- `frost_tbtc_finalize_sign_round`
- `frost_tbtc_build_taproot_tx`
- `frost_tbtc_refresh_shares`
- `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)
- 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 Expand Up @@ -286,8 +289,10 @@ rewrite architecture.
t-of-n contribution handling and filter signing-package commitments to actual
contributing participants; complete keep-core cohort-selection wiring and
non-full-cohort integration coverage.
- Refresh epoch policy: keep `refresh_epoch` monotonic via internal counter
semantics (do not use wall-clock values for refresh ordering).
- Share refresh: add a multi-round, zero-constant FROST refresh protocol before
enabling `RefreshShares`; the retained one-shot ABI must fail closed rather
than manufacture replacement share bytes. Persisted metadata from the retired
synthetic stub is non-authoritative for refresh cadence and key continuity.

## Validation command

Expand Down
5 changes: 5 additions & 0 deletions pkg/tbtc/signer/include/frost_tbtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ TbtcSignerResult frost_tbtc_persist_distributed_dkg_key_package(const uint8_t* r

TbtcSignerResult frost_tbtc_new_signing_package(const uint8_t* request_ptr, size_t request_len);
TbtcSignerResult frost_tbtc_build_taproot_tx(const uint8_t* request_ptr, size_t request_len);
/*
* Reserved ABI: fails closed with terminal error code
* `cryptographic_refresh_not_supported` until a multi-round, zero-constant
* FROST refresh protocol is implemented.
*/
TbtcSignerResult frost_tbtc_refresh_shares(const uint8_t* request_ptr, size_t request_len);

/*
Expand Down
12 changes: 12 additions & 0 deletions pkg/tbtc/signer/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,10 @@ pub struct RefreshSharesRequest {
pub current_shares: Vec<ShareMaterial>,
}

/// Reserved response shape for a future cryptographic share-refresh protocol.
/// The current one-shot endpoint always rejects because it cannot safely run
/// the required multi-round FROST refresh, returning the terminal error code
/// `cryptographic_refresh_not_supported`.
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct RefreshSharesResult {
pub session_id: String,
Expand All @@ -500,11 +504,19 @@ pub struct RefreshCadenceStatusRequest {
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct RefreshCadenceStatusResult {
pub session_id: String,
/// Number of cryptographically valid refreshes. Always zero until the
/// versioned multi-round protocol is implemented.
pub refresh_count: u64,
/// Epoch of the last cryptographically valid refresh. Always zero while
/// `RefreshShares` is reserved and fail-closed.
pub last_refresh_epoch: u64,
pub cadence_seconds: u64,
/// Durable DKG creation deadline, or zero when untrusted legacy refresh
/// metadata has no DKG anchor and must be treated as immediately overdue.
pub next_refresh_due_unix: u64,
pub overdue: bool,
/// False when persisted metadata from the retired synthetic refresh stub is
/// detected; that metadata never establishes key continuity.
pub continuity_preserved: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub continuity_reference_key_group: Option<String>,
Expand Down
Loading
Loading