did-btcr2-js

ADR 043: k-of-n Fallback Signing Protocol for Aggregate Beacons

Status: Accepted

Date: 2026-06-24

Branch / PR: feat/aggregation-non-inclusion

References: ADR 027, ADR 038, ADR 039, ADR 040, ADR 041, ADR 042

Context

ADR 042 replaced the key-path-only aggregate beacon output with a hybrid Taproot output: an internal key (the cohort’s n-of-n MuSig2 aggregate) committing to a script tree of a k-of-n fallback leaf (leaf A, a BIP-342 OP_CHECKSIGADD multisig) and a CSV recovery leaf (leaf B). ADR 042 delivered the first increment (the recovery leaf, the Merkle-root tweak, and the recovery spend) and specified the second: add leaf A and the path-selection cascade so that when the optimistic n-of-n key path stalls, any k present members can still complete the announcement.

ADR 042 fixed the on-chain output shape and the funding model but deliberately left the runtime protocol for the fallback unspecified: how k is chosen and advertised, how members authorize the fallback spend, how the coordinator assembles it, and how the cohort guarantees it never finalizes two competing spends of its single UTXO. This ADR records those decisions, made while implementing the fallback increment, plus two output-construction facts that the fallback (and the existing optimistic path) depend on for an on-chain-spendable transaction.

The threat model is unchanged from ADR 027 and ADR 038: the coordinating service is untrusted (it never holds a signing secret and only aggregates public material), individual cohort members may defect or go offline, and a member must never be induced to authorize something it did not agree to.

Decision

1. The fallback threshold k is an advertised cohort condition, defaulting to n-1

k is added to the cohort conditions of ADR 039 as an optional fallbackThreshold. When a cohort advertises it, it is validated as a positive integer not exceeding the advertised maximum participant count; the binding upper bound against the actual finalized cohort size n is enforced when the beacon address is computed (k must be in [1, n]). When unadvertised, k resolves to max(1, n-1): tolerate one missing or defecting signer, the smallest useful fallback witness. The service and every participant resolve k from the same advertised-or-default rule against the same n, so all parties derive the identical script tree and beacon address. k is part of what the funded address commits to: a different k is a different leaf A and a different address.

2. Leaf A is a p2tr_ms over the BIP-327-sorted x-only cohort keys, in a fixed leaf order

Leaf A is built from the cohort’s own independent BIP-340 keys (no new key material, consistent with ADR 038): the compressed cohort keys are sorted per BIP-327 (the same ordering the MuSig2 internal key uses) and reduced to x-only, and p2tr_ms(k, xOnlyKeys) produces the k-of-n OP_CHECKSIGADD leaf. The script tree’s leaf order is canonical: fallback (leaf A) then recovery (leaf B). For the current two-leaf tree the Merkle root is invariant to leaf order (a TapBranch sorts its two child hashes), but fixing the order keeps the construction deterministic and reviewable and is consensus-affecting should the tree ever grow past two leaves, so the order is asserted at the single seam that builds the leaves.

3. Fallback signing is a dedicated two-message exchange of standalone signatures, with no nonce round

The fallback uses two new messages distinct from the MuSig2 step:

Unlike MuSig2, a script-path OP_CHECKSIGADD signature is an independent per-signer signature, so there is no nonce-commitment round: a member signs in one shot. The coordinator collects signatures, binds each to its sender (the signature must verify against the sighash and the carried key must be the sender’s own cohort key), and once it holds k valid distinct signatures it assembles the witness. A k-of-n OP_CHECKSIGADD leaf is satisfied by exactly k signatures (the trailing <k> NUMEQUAL fails for any other count), so the assembler injects exactly k and the coordinator holds no signing secret at any point. This per-signer one-shot signature is also HSM/KeyManager-drivable, the property ADR 038 found impossible for MuSig2.

Two new protocol phases mark the fallback on each side (a service “fallback requested” phase and a participant “awaiting fallback signature” phase), siblings of the existing signing phases.

4. A single committed path per UTXO, enforced by a latch set only after the state machine accepts the transition

The optimistic key-path spend and the fallback script-path spend are two valid spends of the same beacon UTXO; broadcasting both is a double-spend attempt. The coordinator’s runner therefore commits each cohort to exactly one path. The commitment is a latch on the cohort’s run context:

A member that already contributed its optimistic partial signature (and is locally “complete”) is still allowed to sign the fallback: the cohort has not finalized (the coordinator only falls back before optimistic completion), those members are exactly the k the fallback needs, and signing both authorizes the same outputs of which at most one witness can ever confirm. The trigger may be driven by an operator decision or wired to the per-cohort stall timer of ADR 040; falling back on stall is opt-in, since it trades the cheaper, more private key-path spend for the larger fallback witness.

5. A member signs only a transaction that anchors the signal it validated

Both signing approvals (the optimistic nonce approval and the fallback approval) sign with SIGHASH_DEFAULT, which commits to every output, while the untrusted coordinator drives output selection. A member therefore refuses to sign unless the transaction carries an OP_RETURN output whose 32-byte payload equals the signal the member validated when the aggregated data was distributed. This binds the member’s signature to the exact announcement it approved (the CAS Announcement Map hash or the SMT root), so a coordinator cannot collect signatures and then anchor a different signal (a stale one, or one whose root omits a victim’s update) under those signatures. The member also recomputes the fallback leaf from its own cohort state rather than trusting the leaf script in the request, binding the script path as well as the outputs. The check is applied to both approvals so the optimistic and fallback paths offer the same guarantee.

6. The aggregation result names its spend path

The final result distinguishes the two outcomes: a key-path result carries the aggregated MuSig2 signature, and a script-path result carries the finalized fallback transaction (whose witness embeds k separate signatures, with no single aggregate signature). Callers that broadcast the result therefore know which path was taken without inspecting the witness.

7. The funded output script is derived from the funded address, and the beacon transaction is parsed permissively

Two construction facts the fallback (and the optimistic path) require for an on-chain-spendable transaction:

These correct the integration of ADR 042’s script-tree output into the transaction builder and the participant’s re-parse; they were latent because the only signing path exercised against funded UTXOs to date does not use the MuSig2 aggregate output.

Consequences

Rejected alternatives