Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
ea3d12e
Harden FROST authorization and Bitcoin broadcast recovery
mswilkison Jul 21, 2026
27c310c
Implement crash-safe FROST retained-group readiness
mswilkison Jul 21, 2026
2dfd96e
Bind FROST activation to signer store identity
mswilkison Jul 21, 2026
11a8629
wip(tbtc): ABI 3.5 inventory/state-witness consumers and signing read…
mswilkison Jul 24, 2026
1928a66
fix(tbtc)!: require signer ABI 4.0 and pin the v2-transcript lib
mswilkison Jul 25, 2026
521fcd5
fix(tbtc): harden retained journal persistence paths
mswilkison Jul 25, 2026
adb05d5
Bind FROST activation to historical deployment epochs
mswilkison Jul 25, 2026
b534e19
fix(tbtc): bind signer readiness to ABI 4.1 state
mswilkison Jul 25, 2026
937aaba
test(tbtc): use secp256k1 retained binding fixture
mswilkison Jul 25, 2026
8470083
Add authenticated native signer state anchoring
mswilkison Jul 25, 2026
1d75161
Harden native signer anchor admission and trust startup
mswilkison Jul 26, 2026
0d50f0d
Reject aggregate memo calls without active owner
mswilkison Jul 26, 2026
d5a429c
Recover native signer anchor trust transitions at startup
mswilkison Jul 26, 2026
7f5ff27
Keep legacy wallets off interactive aggregate memo ownership
mswilkison Jul 26, 2026
f9de3e3
ci: pin frost signer mirror to the ABI 4.3 trust-transition head
mswilkison Jul 26, 2026
643b2ab
Add native signer anchor bootstrap provisioning ceremony
mswilkison Jul 26, 2026
d3fdb9a
test(tbtc): cover native signer anchor bootstrap provisioning ceremony
mswilkison Jul 26, 2026
0c32250
Add native signer anchor bootstrap initialize client
mswilkison Jul 27, 2026
e037450
test(tbtc): cover bootstrap initialize client protocol
mswilkison Jul 27, 2026
6cc6f5a
Keep scaffold-era signer material off retained FROST key-group binding
mswilkison Jul 27, 2026
1749bfe
test: align tagged FROST suites with anchor barrier and memo ownership
mswilkison Jul 27, 2026
782f9a3
fix(tbtc): harden FROST activation durability paths
mswilkison Jul 29, 2026
d73af44
Add manifest-bound retained FROST history source
mswilkison Jul 21, 2026
64deb8e
Harden retained FROST history semantics
mswilkison Jul 25, 2026
a3cf577
Bind retained FROST activation transcripts
mswilkison Jul 25, 2026
126654b
Cache FROST activation reconciliation asynchronously
mswilkison Jul 25, 2026
1c2727d
Require quorum certificates for FROST quarantine lifts
mswilkison Jul 25, 2026
448a36d
Require quorum checkpoints for FROST history
mswilkison Jul 25, 2026
e5fffa5
Harden FROST checkpoint trust and recovery
mswilkison Jul 26, 2026
49b1fbd
Harden retained history endpoint identity
mswilkison Jul 26, 2026
f856d53
Route the primary Ethereum chain through an identity-frozen transport
mswilkison Jul 26, 2026
26a8ef4
fix(tbtc): enforce live activation and history bounds
mswilkison Jul 28, 2026
5186668
fix(tbtc): harden journal and outbox recovery
mswilkison Jul 28, 2026
2dcabf7
fix(tbtc): bind activation signatures to outbox state
mswilkison Jul 29, 2026
aa77036
fix(tbtc): preserve FROST liveness during replay
mswilkison Jul 29, 2026
24254d0
test(tbtc): relax WSS timeout watchdog
mswilkison Jul 29, 2026
e243bcf
fix(tbtc): reconcile externally broadcast variants
mswilkison Jul 29, 2026
c692248
fix(tbtc): harden retained history transport startup
mswilkison Jul 29, 2026
d416220
fix(tbtc): tolerate endpoint availability skew
mswilkison Jul 29, 2026
9e89555
feat(tbtc): retained FROST wallet history source and identity-frozen …
mswilkison Jul 29, 2026
592e060
fix(ethereum): share RPC limiter with FROST reads
mswilkison Jul 29, 2026
182b9c9
fix(tbtc): cache signer readiness during authorization
mswilkison Jul 29, 2026
5431ea8
fix(tbtc): recheck retained journal before signing
mswilkison Jul 29, 2026
d33fc50
fix(tbtc): fail over retained TLS replicas
mswilkison Jul 29, 2026
28ce22b
fix(ethereum): cancel FROST limiter waits
mswilkison Jul 29, 2026
009c727
fix(ethereum): make shared limiter context-aware
mswilkison Jul 29, 2026
7f3f182
fix(tbtc): admit DKG before readiness
mswilkison Jul 29, 2026
853e082
fix(tbtc): fail over primary TLS profiles
mswilkison Jul 29, 2026
3b7fa2f
fix(bitcoin): add canonical Electrum status
mswilkison Jul 29, 2026
eccebb0
fix: reconcile canonical replica observations
mswilkison Jul 29, 2026
8ea4b02
fix(tbtc): drain outbox before unlock
mswilkison Jul 29, 2026
862db37
Retire orphaned FROST DKG packages
mswilkison Jul 29, 2026
cde74f0
Keep FROST signing epoch group-consistent
mswilkison Jul 29, 2026
4a4a7cd
Preserve unresolved FROST DKG packages
mswilkison Jul 29, 2026
338df93
Harden FROST DKG package cleanup
mswilkison Jul 29, 2026
cca329d
Defer FROST DKG package retirement
mswilkison Jul 29, 2026
7f3aa2d
Pin FROST DKG retirement state
mswilkison Jul 30, 2026
410f6a6
Protect DKG packages from stale retirement snapshots
mswilkison Jul 30, 2026
60b90cb
Handle legacy and re-included FROST DKG boundaries
mswilkison Jul 30, 2026
692a321
fix(tbtc): preserve partially persisted FROST DKG shares
mswilkison Jul 30, 2026
82e19f4
test(tbtc): cover destructive FROST DKG reconciliation paths
mswilkison Jul 30, 2026
32b4dbd
fix(tbtc): gate FROST signing on quarantine and its own durable advance
mswilkison Jul 30, 2026
5df61b9
fix(tbtc): adopt orphan FROST journal batches without a restart
mswilkison Jul 30, 2026
57e6431
fix(tbtc): bound FROST journal files at write time
mswilkison Jul 30, 2026
d6c8a46
fix(tbtc): match the signer's six-record terminal witness reserve in Go
mswilkison Jul 30, 2026
37b4e36
fix(tbtc): amortize the pre-sign generation reservation over its work…
mswilkison Jul 30, 2026
6a63657
test(tbtc): cover the guarded HTTPS round trip end to end
mswilkison Jul 30, 2026
a864911
fix(tbtc): surface rejected Bitcoin rebroadcasts during replay
mswilkison Jul 30, 2026
0651412
fix(tbtc): retain retained-endpoint peers by separation identity
mswilkison Jul 30, 2026
957b026
docs(tbtc): state what binds the cached handshake snapshots
mswilkison Jul 30, 2026
1cef89d
fix(tbtc): reserve the signer's quarantine records in the Go geometry…
mswilkison Jul 30, 2026
5c4ecd9
ci: pin the signer mirror to the ABI 4.4 retirement head
mswilkison Jul 30, 2026
4f054e8
ci: compare the witness geometry reservations across languages
mswilkison Jul 30, 2026
c9977a3
fix(tbtc): admit the signing window's own advance, and attest live state
mswilkison Jul 30, 2026
6825402
docs(tbtc): state what the generation reservation does not cover
mswilkison Jul 30, 2026
adacf55
test(tbtc): cover preserving FROST DKG reconciliation and caller admi…
mswilkison Jul 30, 2026
f7fb16d
style(tbtc): gofmt the retained transport test
mswilkison Jul 30, 2026
fcc4f08
fix(tbtc): derive the FROST journal file bound and ride out unreachab…
mswilkison Jul 30, 2026
b38f8e4
fix(frost): stop a transport blip from terminally poisoning the signe…
mswilkison Jul 31, 2026
9083658
docs(tbtc): document the offline FROST anchor rotation ceremony
mswilkison Jul 31, 2026
44ad440
fix(tbtc): fail the activation health verdict on a poisoned signer an…
mswilkison Jul 31, 2026
1394663
fix(tbtc): stop admitting FROST work a poisoned anchor cannot finish
mswilkison Jul 31, 2026
725e3c0
feat(tbtc): make a silently non-signing FROST node visible before act…
mswilkison Jul 31, 2026
0e4d69f
fix(tbtc): register the anchor admission rejection counters
mswilkison Jul 31, 2026
b2f6990
docs(tbtc): cover the poisoned anchor in the rotation runbook
mswilkison Jul 31, 2026
2fc4da8
docs(tbtc): name the rollback the anchor actually defends against
mswilkison Jul 31, 2026
c616e86
fix(tbtc): reserve FROST anchor capacity per input, not per batch
mswilkison Jul 31, 2026
9da4cce
docs(tbtc): correct the revision cost in the terms table
mswilkison Jul 31, 2026
5247561
fix(tbtc): align signer health with workload capacity
mswilkison Jul 31, 2026
276f01b
fix(tbtc): preserve admitted signing capacity
mswilkison Jul 31, 2026
0ae0cf0
fix(tbtc): classify transient signer dependencies
mswilkison Jul 31, 2026
744fe5e
fix(tbtc): bound authorization dependency retries
mswilkison Jul 31, 2026
02a2840
fix(spv): propagate target wallet lookup failures
mswilkison Jul 31, 2026
97bb190
fix(tbtc): preserve signing wire and DKG recovery
mswilkison Jul 31, 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
53 changes: 53 additions & 0 deletions .github/workflows/frost-cgo-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,49 @@ jobs:
test -f "$lib" || { echo "libfrost_tbtc.so not found at $lib"; exit 1; }
echo "FROST_LIB_DIR=${CARGO_TARGET_DIR}/debug" >> "$GITHUB_ENV"

- name: Verify the witness geometry reservations agree across languages
run: |
set -euo pipefail
# The Go validators mint and pre-verify the offline-authority-signed trust
# certificates, so a geometry Go accepts must be exactly a geometry the signer
# accepts. Go cannot see the crate (it lives on the mirror branch), so its own
# test can only pin its own constants - it cannot notice the signer moving.
# This job can: it has the pinned crate checked out, so it compares the two
# sources directly. A reservation raised in Rust fails HERE, in the same gate
# that builds the pinned library, instead of surfacing after an operator has
# already run the offline signing ceremony against a geometry the node rejects.
rust_const() {
grep -oE "pub\(crate\) const $1: usize = [0-9]+" \
_signer-mirror/pkg/tbtc/signer/src/engine/store.rs \
| grep -oE '[0-9]+$'
}
go_const() {
grep -oE "$1 uint64 = [0-9]+" \
pkg/frost/signing/native_tbtc_signer_state_anchor_trust.go \
| grep -oE '[0-9]+$'
}
mismatch=0
check() {
rust_value="$(rust_const "$1" || true)"
go_value="$(go_const "$2" || true)"
if [ -z "$rust_value" ] || [ -z "$go_value" ]; then
echo "could not read $1 (rust) / $2 (go); a constant was renamed"
mismatch=1
return
fi
if [ "$rust_value" != "$go_value" ]; then
echo "witness geometry drift: $1 is [$rust_value] but $2 is [$go_value]"
mismatch=1
fi
}
check TBTC_SIGNER_STATE_WITNESS_ROTATION_TERMINAL_RECORD_RESERVATION \
NativeTBTCSignerStateWitnessRotationTerminalRecordReservation
check TBTC_SIGNER_STATE_WITNESS_QUARANTINE_RECORD_RESERVATION \
NativeTBTCSignerStateWitnessQuarantineRecordReservation
test "$mismatch" -eq 0 || {
echo "update the Go reservation constants and their validator in the same change"
exit 1; }

- name: Verify the engine ABI symbols are exported
run: |
set -euo pipefail
Expand All @@ -86,13 +129,23 @@ jobs:
missing=0
for sym in \
frost_tbtc_persist_distributed_dkg_key_package \
frost_tbtc_retire_distributed_dkg_key_packages \
frost_tbtc_dkg_part1 \
frost_tbtc_derive_interactive_attempt_context \
frost_tbtc_interactive_session_open \
frost_tbtc_interactive_session_abort \
frost_tbtc_new_signing_package \
frost_tbtc_interactive_aggregate \
frost_tbtc_verify_signature_share \
frost_tbtc_durable_store_identity \
frost_tbtc_retained_key_package_inventory \
frost_tbtc_state_witness_proof \
frost_tbtc_state_witness_tip \
frost_tbtc_state_anchor_trust_head \
frost_tbtc_transition_state_witness_anchor \
frost_tbtc_state_anchor_bootstrap_facts \
frost_tbtc_acknowledge_state_witness_checkpoint \
frost_tbtc_recover_state_witness_checkpoint \
frost_tbtc_version \
frost_tbtc_abi_version; do
if ! nm -D --defined-only "$lib" | grep -q " ${sym}$"; then
Expand Down
2 changes: 1 addition & 1 deletion ci/frost-signer-pin.env
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
#
# After the scaffold and mirror branches merge into one, replace the cross-branch
# checkout with an in-tree cargo build and retire this pin (keep the gate).
FROST_SIGNER_MIRROR_REF=6e0fa9741ffb6b0bb5603eabe26fb4cc1b13ecd9
FROST_SIGNER_MIRROR_REF=08b6d6f40027016101f32c1ffc509fde4746d0a2
1 change: 1 addition & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func init() {
EthereumCommand,
MaintainerCommand,
MaintainerCliCommand,
TBTCSignerCommand,
)
}

Expand Down
76 changes: 74 additions & 2 deletions cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,64 @@ Environment variables:
func start(cmd *cobra.Command) error {
ctx := context.Background()

beaconChain, tbtcChain, blockCounter, signing, operatorPrivateKey, err :=
ethereum.Connect(ctx, clientConfig.Ethereum)
var primaryEthereumTransport *tbtc.FrostPrimaryEthereumTransport
var err error
if clientConfig.Tbtc.EnableFrostPreSignAuthorization &&
!clientConfig.LibP2P.Bootstrap {
historyConfig := clientConfig.Tbtc.FrostRetainedGroupHistory
primaryEthereumTransport, err =
tbtc.NewFrostPrimaryEthereumTransport(
ctx,
tbtc.FrostPrimaryEthereumTransportConfig{
URL: clientConfig.Ethereum.URL,
RequestTimeout: historyConfig.RequestTimeout,
TLSRootCAs: historyConfig.PrimaryTLSRootCAs,
Resolver: historyConfig.Resolver,
},
)
if err != nil {
return fmt.Errorf(
"cannot initialize guarded primary Ethereum transport: [%w]",
err,
)
}
}

var (
beaconChain *ethereum.BeaconChain
tbtcChain *ethereum.TbtcChain
blockCounter chain.BlockCounter
signing chain.Signing
operatorPrivateKey *operator.PrivateKey
)
if primaryEthereumTransport != nil {
beaconChain,
tbtcChain,
blockCounter,
signing,
operatorPrivateKey,
err = ethereum.ConnectWithClient(
ctx,
clientConfig.Ethereum,
primaryEthereumTransport.Client(),
)
} else {
beaconChain,
tbtcChain,
blockCounter,
signing,
operatorPrivateKey,
err = ethereum.Connect(ctx, clientConfig.Ethereum)
}
if err != nil {
if primaryEthereumTransport != nil {
primaryEthereumTransport.Close()
}
return fmt.Errorf("error connecting to Ethereum node: [%v]", err)
}
if primaryEthereumTransport != nil {
defer primaryEthereumTransport.Close()
}

netProvider, err := initializeNetwork(
ctx,
Expand Down Expand Up @@ -162,6 +215,25 @@ func start(cmd *cobra.Command) error {
btcChain,
)

var retainedGroupHistorySource interface{ Close() }
if clientConfig.Tbtc.EnableFrostPreSignAuthorization {
source, err := tbtc.NewFrostRetainedGroupHistorySource(
ctx,
clientConfig.Tbtc.FrostRetainedGroupHistory,
primaryEthereumTransport,
primaryEthereumTransport.ChainID(),
)
if err != nil {
return fmt.Errorf(
"cannot initialize independent FROST retained-group history source: [%w]",
err,
)
}
retainedGroupHistorySource = source
defer retainedGroupHistorySource.Close()
clientConfig.Tbtc.FrostRetainedGroupHistorySource = source
}

err = tbtc.Initialize(
ctx,
tbtcChain,
Expand Down
Loading
Loading