Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Frost_pay — PoC

A small proof-of-concept touching the primitives a Bitcoin coordination / recovery layer (post-Coldcard) would need to compose cleanly:

  1. FROST threshold Schnorr signing (2-of-3). No single device or vendor ever holds a full private key. A 2-of-3 quorum can still produce a valid signature under the shared group key even when one participant (e.g. a lost phone) never shows up. This is the actual hard problem in post-Coldcard recovery: not "how do I back up a seed phrase" but "how do I reach quorum without a single point of failure or a single vendor dependency."

  2. BIP-352 Silent Payments (sketch). The threshold group key from (1) is used as the receiver's spend key (B_spend) for a silent payment address. Because spending authority is still gated by the 2-of-3 quorum, the recovery guarantee holds all the way through to the silent-payment output — not just at the wallet level.

Toolchain note

This was built in a sandboxed environment with no network path to install a newer Rust toolchain — only rustc 1.75 was available via apt. The official frost-secp256k1 crate (and its frost-core dependency) requires rustc 1.81+, so rather than fake the result, src/main.rs implements the FROST signing math directly against k256's curve arithmetic:

  • Shamir secret sharing for the trusted-dealer keygen (f(x) = s0 + a1*x)
  • Per-signer nonce commit/reveal (d, e and their curve points)
  • Binding factors (rho_i) and group commitment R
  • BIP340-style Schnorr challenge c = H(R || Y || m)
  • Lagrange-coefficient interpolation for signature-share aggregation

This is the same protocol frost-core implements internally — on a normal toolchain, swapping this out for the real frost-secp256k1 crate would take about 20 lines and drop most of this file. Kept the from-scratch version here deliberately, since it's a more honest signal of understanding the protocol than a library call would be.

The signature is verified in-process (z*G == R + c*Y) and the code has been run repeatedly, including with different 2-of-3 signer subsets ({1,2} and {2,3}), to confirm it isn't a lucky pass.

Running it

cargo run

Expected output includes:

Group public key (anchors the silent payment spend key): 03...
2-of-3 signature produced with participants [1, 2] only (participant(s) [3] absent).
Signature verifies against group key: true
...
B_spend (cold, FROST 2-of-3 group key): 03...

What's deliberately out of scope

  • Real distributed key generation (Pedersen DKG) — this uses a trusted dealer for simplicity. A real deployment would run FROST DKG so no party ever sees s0.
  • bech32m encoding of the actual sp1... address — the fingerprint hash stands in for it.
  • The sender-side ECDH tweak computation from BIP-352 (per-input, per-transaction).
  • Any persistence, networking, or coordination transport between signers — this is single-process for clarity.

Next steps if this goes further

  • Swap in frost-secp256k1 + real DKG once on a normal toolchain.
  • Implement the sender-side tweak and full bech32m address encoding per BIP-352.
  • Design the actual quorum-recovery UX: how a 3rd signer gets replaced (key rotation) without re-deriving B_spend, and what happens if 2 of 3 quorum members are simultaneously unavailable.

About

A small proof-of-concept touching the primitives a Bitcoin coordination

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages