Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
127 commits
Select commit Hold shift + click to select a range
2e3570e
feat(tbtc): UTXO reservation wallet-side foundations
mswilkison Aug 7, 2026
77fca94
fix(tbtcpg): align GetRedemptionParameters call with struct return
mswilkison Aug 7, 2026
7826468
fix(tbtc): validate reservation proposal payloads
mswilkison Aug 9, 2026
62b18c1
fix(tbtc): bind reservations to action generations
mswilkison Aug 9, 2026
b4f6394
fix(tbtc): bind dissolution inputs to action snapshot
mswilkison Aug 9, 2026
277865c
feat(tbtc): regenerate ABI bindings for reservation router surface
piotr-roslaniec Aug 26, 2026
e49e954
feat(tbtc): implement reservation read/validate methods against real …
piotr-roslaniec Aug 26, 2026
4ba2f22
feat(tbtc): add reservation write methods, additional views, and even…
Aug 26, 2026
0535779
feat(tbtc): add reservation methods to tbtcpg and spv Chain interfaces
piotr-roslaniec Aug 26, 2026
ac58650
feat(tbtc): implement reservation watchers
Aug 26, 2026
e37211b
feat(tbtc): implement reservation acceptance executor
piotr-roslaniec Aug 26, 2026
603ad0d
feat(tbtc): implement reservation re-anchor executor
piotr-roslaniec Aug 26, 2026
2bd8731
Merge branch 'm1/h-acceptance' into m1/keep-core-client
piotr-roslaniec Aug 26, 2026
daeb6af
Merge branch 'm1/h-reanchor' into m1/keep-core-client
piotr-roslaniec Aug 26, 2026
c29de0b
merge: parallel builders for acceptance, re-anchor, watchers
piotr-roslaniec Aug 26, 2026
4898545
feat(tbtc): wire reservation executors and watchers
piotr-roslaniec Aug 26, 2026
5daf210
fix: add context to GetTransactionConfirmations call in reservation a…
piotr-roslaniec Aug 27, 2026
b14a388
merge: pull in reservations-epic base updates (bitcoin.Chain context-…
piotr-roslaniec Aug 27, 2026
7cf8106
feat(spv): wire real reservation re-anchor SPV proof discovery
piotr-roslaniec Sep 1, 2026
6a8162b
feat(spv): implement real ReservationActionTimeoutWatcher.Run loop
piotr-roslaniec Sep 1, 2026
7108928
fix(spv): reject stale reservation re-anchor action generations befor…
piotr-roslaniec Sep 1, 2026
7824ad2
docs(spv): correct nonce-staleness window framing in code comment
piotr-roslaniec Sep 1, 2026
64fc398
fix(spv): skip, don't abort the round, on stale reservation re-anchor…
piotr-roslaniec Sep 1, 2026
e052162
docs(spv): correct won't-recur claim on stale/mismatched reanchor skips
piotr-roslaniec Sep 1, 2026
20cb160
fix(tbtc,spv): wire reservation watchers to real chain calls and add …
piotr-roslaniec Sep 1, 2026
1de2631
fix(clientinfo): gate reservation metrics registration behind config …
piotr-roslaniec Sep 1, 2026
753d717
test(ethereum): add unit tests for reservation ABI conversion functions
piotr-roslaniec Sep 1, 2026
cb8ad1a
fix(tbtcpg): reservation acceptance/re-anchor correctness fixes and c…
piotr-roslaniec Sep 1, 2026
72373fc
feat(tbtc): switch reservation proposal marshaling to protobuf
piotr-roslaniec Sep 1, 2026
c8eb541
fix(tbtc): wire reservation actions into the coordination checklist
piotr-roslaniec Sep 1, 2026
cb43346
test(tbtc): multi-signer simulated integration test for reservation c…
piotr-roslaniec Sep 1, 2026
bcb4725
test(reservations): M2 test-coverage backfill (7 of 8 items)
piotr-roslaniec Sep 1, 2026
5a645ab
fix(tbtc): regenerate message.pb.go with pinned protoc/protoc-gen-go
piotr-roslaniec Sep 1, 2026
ff045ff
Merge branch 'm1/reservation-protobuf-marshaling' into m1/reservation…
piotr-roslaniec Sep 1, 2026
cdca713
Merge branch 'm1/reservation-coordination-checklist' into m1/reservat…
piotr-roslaniec Sep 1, 2026
19eeb1b
Merge branch 'm1/reservation-multisigner-integration-test' into m1/re…
piotr-roslaniec Sep 1, 2026
d75ae12
fix(tbtc): dispatch reservation coordination results, gate on activat…
piotr-roslaniec Sep 1, 2026
29ce21a
fix(ethereum): remove dead reservation router API, add conversion tes…
piotr-roslaniec Sep 1, 2026
4bfa523
fix(clientinfo): split reservation metric names from the always-regis…
piotr-roslaniec Sep 1, 2026
3eda058
fix(spv): fix reservation watcher notifications, proof loop, and wiri…
piotr-roslaniec Sep 1, 2026
c48d17b
fix(tbtcpg): additional reservation acceptance/reanchor fixes and cov…
piotr-roslaniec Sep 1, 2026
757c6d8
fix(tbtc): resolve review findings across coordination, reservation, …
piotr-roslaniec Sep 1, 2026
85af2bd
fix(tbtcpg): guard reservation acceptance/reanchor tasks against stuc…
piotr-roslaniec Sep 1, 2026
e202c2c
fix(spv): correct reservation watcher ordering, RPC scan cost, and wi…
piotr-roslaniec Sep 1, 2026
7054614
fix(client): remove dead reservation router API surface, wire watcher…
piotr-roslaniec Sep 1, 2026
0f62ab2
Merge branch 'm1/keep-core-client' into m1/reservation-readiness-fixes
piotr-roslaniec Sep 2, 2026
fe05305
Merge branch 'm1/keep-core-client' into m1/reservation-readiness-fixes
piotr-roslaniec Sep 2, 2026
b9b0fe2
Merge branch 'm1/reservation-readiness-fixes' into m1/reservation-pro…
piotr-roslaniec Sep 2, 2026
b852948
Merge branch 'm1/reservation-protobuf-marshaling' into m1/reservation…
piotr-roslaniec Sep 2, 2026
07db77c
Merge branch 'm1/reservation-coordination-checklist' into m1/reservat…
piotr-roslaniec Sep 2, 2026
ec9212f
Merge branch 'm1/reservation-multisigner-integration-test' into m1/re…
piotr-roslaniec Sep 2, 2026
5149267
fix(tbtcpg): rewrite reservation acceptance task stateless
piotr-roslaniec Sep 2, 2026
b91c818
fix(tbtcpg): fix reservation reanchor target-wallet cache and dead check
piotr-roslaniec Sep 2, 2026
0f39259
test(tbtcpg): cover reservation tx max-fee boundary
piotr-roslaniec Sep 2, 2026
4fdb9bb
fix(spv): tighten reservation proof transaction matching
piotr-roslaniec Sep 2, 2026
09c03b0
fix(spv): bound reservation action timeout wallet scan
piotr-roslaniec Sep 2, 2026
695590d
fix(spv): fix stale-deposit watch fallback and nonce lookup
piotr-roslaniec Sep 2, 2026
dbf4ade
fix(spv): make reservation watcher startup catch-up non-fatal
piotr-roslaniec Sep 2, 2026
1a43292
fix(tbtc): fix past-due activation block and doc/overflow issues
piotr-roslaniec Sep 2, 2026
9f09fb3
feat(tbtc): add String() methods for ReservationActionType/State
piotr-roslaniec Sep 2, 2026
fc128f0
fix(spv): correct reservation action re-check guard behavior and cove…
piotr-roslaniec Sep 2, 2026
f5c5e35
Merge remote-tracking branch 'origin/m1/keep-core-client' into m1/res…
piotr-roslaniec Sep 2, 2026
0a427b6
ci(client): tolerate known tbtc-v2 npm ReservationRouter gap (#4281)
piotr-roslaniec Sep 2, 2026
7210a7c
Revert "ci(client): tolerate known tbtc-v2 npm ReservationRouter gap …
piotr-roslaniec Sep 2, 2026
3298ae0
fix(gen): vendor ReservationRouter artifact fallback for missing npm …
piotr-roslaniec Sep 2, 2026
ee30610
fix(gen): patch stale Bridge/WalletProposalValidator npm artifacts wi…
piotr-roslaniec Sep 2, 2026
0358cc7
ci(tbtc): unblock ReservationRouter bindings via tbtc-v2 PR #1112 shim
piotr-roslaniec Sep 2, 2026
91f8c59
ci(tbtc): pin Node 22 for the tbtc-v2 shim build
piotr-roslaniec Sep 2, 2026
e6d0bfe
ci(tbtc): drop the tbtc-v2 shim's local deploy step
piotr-roslaniec Sep 2, 2026
ee942a8
feat(tbtc): switch reservation proposal marshaling to protobuf
piotr-roslaniec Sep 1, 2026
87c6a68
test(tbtc): address review findings on reservation proposal marshalin…
piotr-roslaniec Sep 2, 2026
d66c7b2
ci(tbtc): treat empty ENVIRONMENT as development in the shim guard
piotr-roslaniec Sep 2, 2026
a7b27fe
feat(tbtc): wire reservation executors and watchers (#4274)
piotr-roslaniec Sep 3, 2026
19e9131
fix(spv): re-verify reservation action generation before SPV proof su…
piotr-roslaniec Sep 3, 2026
bb3dcb3
test(tbtc): add reservation proposal marshaling coverage (#4277)
piotr-roslaniec Sep 3, 2026
b50918f
fix(tbtc): check reservation actions on every coordination window
piotr-roslaniec Sep 3, 2026
63aaa1a
feat(tbtc): switch reservation proposal marshaling to protobuf
piotr-roslaniec Sep 1, 2026
edb82c7
test(tbtc): multi-signer simulated integration test for reservation c…
piotr-roslaniec Sep 1, 2026
014754d
fix(tbtc): bound coordination test timeout, dedupe harness, fix leak
piotr-roslaniec Sep 3, 2026
bf97e4e
fix(tbtc): guard coordination fan-in against lost/duplicate reports
piotr-roslaniec Sep 3, 2026
2f34a36
Revert "fix(tbtc): guard coordination fan-in against lost/duplicate r…
piotr-roslaniec Sep 3, 2026
84e870c
fix(net/local,tbtc): close broadcast-channel registry leak at its root
piotr-roslaniec Sep 3, 2026
80a4c61
fix(tbtc): drop redundant per-invocation nonce, fix stale doc claim
piotr-roslaniec Sep 3, 2026
b88eac7
fix(net/local,net/retransmission): scope channel release, guard ticke…
piotr-roslaniec Sep 3, 2026
4b7ee24
fix(tbtc): coordination test correctness fixes and doc corrections
piotr-roslaniec Sep 3, 2026
99f5f0a
fix(tbtcpg): exclude reservation-vault deposits from deposit sweep se…
piotr-roslaniec Sep 3, 2026
8f03ffa
fix(tbtc): guard reservation look-back underflow and verify target wa…
piotr-roslaniec Sep 3, 2026
7cbb8cc
fix(tbtc): nil-guard marshaling and symmetric zero-hash rejection
piotr-roslaniec Sep 3, 2026
602d0ef
fix(tbtc): derive reservations activation block from ethereum network
piotr-roslaniec Sep 3, 2026
437f2b9
fix(cmd): mirror reservation misconfiguration warning at startup
piotr-roslaniec Sep 3, 2026
972b2f9
feat(clientinfo): add reservation saturation monitoring gauges
piotr-roslaniec Sep 3, 2026
9e42103
fix(tbtc): restore exported name in AssembleReservationAnchorTransact…
piotr-roslaniec Sep 3, 2026
6146987
test(reservations): address multi-agent review findings
piotr-roslaniec Sep 3, 2026
c6c5025
fix(maintainer/spv): non-lossy retry eviction and stale-deposit timeo…
piotr-roslaniec Sep 3, 2026
726f05e
fix(tbtcpg): reservation acceptance/re-anchor eth_getLogs bounds, non…
piotr-roslaniec Sep 3, 2026
f23577f
Merge remote-tracking branch 'origin/m1/reservation-multisigner-integ…
piotr-roslaniec Sep 3, 2026
397b340
test(tbtc): multi-signer simulated integration test for reservation c…
piotr-roslaniec Sep 3, 2026
19b0a4f
fix(tbtc): remove frequency gate on reservation checklist actions (#4…
piotr-roslaniec Sep 3, 2026
ff1eba7
style: gofmt import ordering and blank-line cleanup
piotr-roslaniec Sep 3, 2026
441b9f8
Merge remote-tracking branch 'origin/reservations-epic' into m1/reser…
piotr-roslaniec Sep 3, 2026
28da573
fix(net/local): absorb release-boundary straggler tick in TestRelease…
piotr-roslaniec Sep 3, 2026
2c38e85
fix(tbtcpg): prevent head-of-line-blocking DoS in reservation acceptance
piotr-roslaniec Sep 3, 2026
f20a3b3
test(reservations): address multi-agent review findings
piotr-roslaniec Sep 3, 2026
59bd97f
fix(tbtc): reservation review remediation (37 findings from multi-age…
piotr-roslaniec Sep 3, 2026
8637a02
fix(net/local): bound the release-boundary settle drain in TestReleas…
piotr-roslaniec Sep 3, 2026
a38e85e
fix(net/local): bound release-boundary settle drain in TestReleaseBro…
piotr-roslaniec Sep 3, 2026
0fad2f7
Merge remote-tracking branch 'origin/reservations-epic' into m1/reser…
piotr-roslaniec Sep 3, 2026
edd054e
test(tbtcpg): assert genuine pending-action state in dedup test
piotr-roslaniec Sep 3, 2026
356d35b
test(reservations): M2 test-coverage backfill (7 of 8 items) (#4280)
piotr-roslaniec Sep 3, 2026
aa6385b
fix(tbtcpg): fail-safe reservation-acceptance error handling and resu…
piotr-roslaniec Sep 4, 2026
0d0d598
fix(tbtcpg,clientinfo): bound reanchor authorizations, fix reservatio…
piotr-roslaniec Sep 4, 2026
489ae89
fix(maintainer/spv): keep live-wallet stale deposits tracked, fix cac…
piotr-roslaniec Sep 4, 2026
459f5df
fix(maintainer/spv): stop evicting unconfirmed action-timeout notific…
piotr-roslaniec Sep 4, 2026
715917a
fix(maintainer/spv): remove dead proof-matching guard and retry/rewin…
piotr-roslaniec Sep 4, 2026
8e50fc9
refactor(maintainer/spv): unexport reservation stranding watcher inte…
piotr-roslaniec Sep 4, 2026
a6eefd9
fix(maintainer/spv): bound startup scan, pre-filter deposits, fix bat…
piotr-roslaniec Sep 4, 2026
82c02d7
docs(maintainer/spv): document mainUtxo as inert in milestone 1
piotr-roslaniec Sep 4, 2026
a255685
fix(tbtc): correct reservation config doc, add Sepolia activation block
piotr-roslaniec Sep 4, 2026
d5ed0a7
fix(ci): track ci-shims artifact placeholder, drop dead epic-only shi…
piotr-roslaniec Sep 4, 2026
c7c1f05
fix(ci): match ci-shims guard to json artifacts, not directory presence
piotr-roslaniec Sep 4, 2026
af4deb6
fix(tbtc): drop fabricated Sepolia activation-block placeholder
piotr-roslaniec Sep 4, 2026
339e805
fix(maintainer/spv): retry a stale-deposit whose reserved-check RPC f…
piotr-roslaniec Sep 4, 2026
674cfa4
fix(maintainer/spv): actually retry a dropped or reverted timeout not…
piotr-roslaniec Sep 4, 2026
c2ea74c
ci: trigger workflow
piotr-roslaniec Sep 4, 2026
c3a9464
Merge remote-tracking branch 'origin/dev' into reservations-epic
piotr-roslaniec Sep 4, 2026
bc7dc16
fix(maintainer/spv): honor operator-configured MaxProofHeaders in res…
piotr-roslaniec Sep 4, 2026
4e2169e
fix(maintainer/spv): default a zero MaxProofHeaders to the package cap
piotr-roslaniec Sep 4, 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
14 changes: 14 additions & 0 deletions .github/workflows/client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ jobs:
with:
environment: ${{ github.event.inputs.environment }}

# TODO(https://github.com/threshold-network/tbtc-v2/pull/1112): remove once
# @keep-network/tbtc-v2 publishes the reservation-router surface (Bridge,
# WalletProposalValidator, RedemptionWatchtower, ReservationRouter, and the
# rest of the tbtc module's required_contracts) under the `development` npm
# tag. Until then, `make get_artifacts` can't fetch these from npm; the gen
# Makefile's vendored fallback artifacts (see
# pkg/chain/ethereum/tbtc/gen/Makefile's ReservationRouter.fallback-artifact.json
# rule and the Bridge/WalletProposalValidator reservation-methods-fallback.json
# patch rules) supply the missing methods for `environment=development` builds
# instead. This directory only exists so the Dockerfile's COPY step (guarded by
# `-n "$(ls -A ...)"`, a no-op when empty) always has a source to copy from; see
# ./ci-shims/tbtc-artifacts and the matching Dockerfile step.
- name: Prepare tbtc-v2 artifact shim directory
run: mkdir -p ci-shims/tbtc-artifacts
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
# Executables
/keep-client

# Temporary CI-only artifact injected before the Docker build; see Dockerfile
# and .github/workflows/client.yml (ReservationRouter tbtc-v2 PR #1112 shim).
/ci-shims/*
!/ci-shims/tbtc-artifacts/
!/ci-shims/tbtc-artifacts/**

# IDEs
.vscode/
.idea/
Expand Down
22 changes: 21 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,31 @@ COPY ./pkg/protocol/inactivity/gen $APP_DIR/pkg/protocol/inactivity/gen
RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.32.0

# Environment is to download published and tagged NPM packages versions.
ARG ENVIRONMENT
# Defaults to `development` to mirror the root Makefile's `ifndef environment`
# fallback (the "Build Docker Build Image" CI step never passes this build-arg).
ARG ENVIRONMENT=development

COPY ./Makefile $APP_DIR/Makefile
RUN make get_artifacts environment=$ENVIRONMENT

# TODO(https://github.com/threshold-network/tbtc-v2/pull/1112): remove once
# @keep-network/tbtc-v2 publishes Bridge/WalletProposalValidator/RedemptionWatchtower/
# ReservationRouter (and the rest of the tbtc module's required_contracts) under the
# `development` npm tag. Until then, `get_artifacts` fetches a tbtc-v2 package whose
# Bridge/WalletProposalValidator/RedemptionWatchtower don't yet expose the reservation
# methods this PR binds against, and has no ReservationRouter artifact at all. The
# `client.yml` workflow locally compiles tbtc-v2 PR #1112 (pinned SHA) and drops its
# compiled ABI artifacts for the tbtc module's required_contracts at
# ./ci-shims/tbtc-artifacts/*.json when it runs; this only overrides the tbtc module's
# artifacts, and only for `environment=development` (PR CI) builds - sepolia/mainnet
# builds and the beacon/ecdsa/threshold modules are untouched.
COPY ./ci-shims/tbtc-artifacts /tmp/tbtc-artifacts
RUN if { [ -z "$ENVIRONMENT" ] || [ "$ENVIRONMENT" = "development" ]; } && ls /tmp/tbtc-artifacts/*.json >/dev/null 2>&1; then \
echo "Using tbtc-v2 module artifacts built from tbtc-v2 PR #1112 (temporary shim)"; \
cp /tmp/tbtc-artifacts/*.json \
$APP_DIR/tmp/contracts/development/@keep-network/tbtc-v2/artifacts/; \
fi

# Need this to resolve imports in generated Ethereum commands.
COPY ./config $APP_DIR/config
RUN make generate environment=$ENVIRONMENT
Expand Down
Empty file.
40 changes: 37 additions & 3 deletions cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/keep-network/keep-core/pkg/tbtcpg"

"github.com/keep-network/keep-common/pkg/persistence"

"github.com/keep-network/keep-core/build"
"github.com/keep-network/keep-core/pkg/bitcoin/electrum"
"github.com/keep-network/keep-core/pkg/operator"
Expand All @@ -22,6 +23,7 @@ import (
"github.com/keep-network/keep-core/pkg/clientinfo"
"github.com/keep-network/keep-core/pkg/firewall"
"github.com/keep-network/keep-core/pkg/generator"
"github.com/keep-network/keep-core/pkg/maintainer/spv"
"github.com/keep-network/keep-core/pkg/net"
"github.com/keep-network/keep-core/pkg/net/libp2p"
"github.com/keep-network/keep-core/pkg/net/retransmission"
Expand Down Expand Up @@ -92,7 +94,11 @@ func start(cmd *cobra.Command) error {
// Wire performance metrics into network provider if available
var perfMetrics *clientinfo.PerformanceMetrics
if clientInfoRegistry != nil {
perfMetrics = clientinfo.NewPerformanceMetrics(ctx, clientInfoRegistry)
perfMetrics = clientinfo.NewPerformanceMetrics(
ctx,
clientInfoRegistry,
clientConfig.Tbtc.Reservations.Enabled,
)
// Type assert to libp2p provider to set metrics recorder
// The provider struct is not exported, so we use interface assertion
if setter, ok := netProvider.(interface {
Expand Down Expand Up @@ -160,9 +166,10 @@ func start(cmd *cobra.Command) error {
proposalGenerator := tbtcpg.NewProposalGenerator(
tbtcChain,
btcChain,
clientConfig.Tbtc.Reservations.Enabled,
)

err = tbtc.Initialize(
resolver, err := tbtc.Initialize(
ctx,
tbtcChain,
btcChain,
Expand All @@ -177,7 +184,34 @@ func start(cmd *cobra.Command) error {
clientConfig.Ethereum.Network,
)
if err != nil {
return fmt.Errorf("error initializing TBTC: [%v]", err)
return fmt.Errorf("cannot initialize TBTC: [%v]", err)
}

// Wire the reservation watchers (stranding, stale-deposit,
// action-timeout) directly against the same tbtcChain handle:
// cmd/start.go already imports both tbtc and spv, so there is no
// import-cycle reason to thread this through tbtc.Initialize via a
// callback type. Gated on the same flag that gates the reservation
// proposal generator tasks above. Failing to wire the watchers is
// fatal: the operator opted into reservations, so a missing
// watcher would silently strand anchors.
if clientConfig.Tbtc.Reservations.Enabled {
if !clientConfig.Maintainer.Spv.Reservations.Enabled {
logger.Warnf("Client reservation proposal generation is enabled; " +
"ensure the paired Maintainer.Spv.Reservations.Enabled flag is also " +
"enabled in the maintainer config for end-to-end operation")
}
if err := spv.WireReservationWatchers(
ctx,
tbtcChain,
tbtcChain,
resolver,
); err != nil {
return fmt.Errorf(
"failed to wire reservation watchers: [%v]",
err,
)
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,14 @@ func TestReadConfigFromFile(t *testing.T) {
readValueFunc: func(c *Config) interface{} { return c.Maintainer.Spv.IdleBackoffTime },
expectedValue: 15 * time.Minute,
},
"Maintainer.Spv.Reservations.Enabled": {
readValueFunc: func(c *Config) interface{} { return c.Maintainer.Spv.Reservations.Enabled },
expectedValue: true,
},
"Tbtc.Reservations.Enabled": {
readValueFunc: func(c *Config) interface{} { return c.Tbtc.Reservations.Enabled },
expectedValue: true,
},
}

for _, filePath := range filePaths {
Expand Down
16 changes: 15 additions & 1 deletion pkg/chain/ethereum/tbtc.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// tbtc.go: TbtcChain adapter construction and shared state. See tbtc_*.go for
// per-concern implementations (tbtc_deposit.go, tbtc_dkg.go, tbtc_moving_funds.go,
// tbtc_redemption.go, tbtc_wallet.go, tbtc_sortition.go, tbtc_inactivity.go).
// tbtc_redemption.go, tbtc_reservation.go, tbtc_wallet.go, tbtc_sortition.go,
// tbtc_inactivity.go).
//
// These files were split out of a single monolithic tbtc.go with no rename
// markers git can detect (each file is a fresh addition, not a tracked move),
Expand Down Expand Up @@ -61,6 +62,10 @@ type TbtcChain struct {
sortitionPool *ecdsacontract.EcdsaSortitionPool
walletProposalValidator *tbtccontract.WalletProposalValidator
redemptionWatchtower *tbtccontract.RedemptionWatchtower
// reservationRouter is the abigen binding for ReservationRouter.sol's ABI
// constructed against the Bridge address (see tbtc_reservation.go for the
// address invariant explanation).
reservationRouter *tbtccontract.ReservationRouter
// ecdsaDkgValidatorAddress optional; when zero, TBTC uses defaultGroupParameters(network).
ecdsaDkgValidatorAddress common.Address

Expand Down Expand Up @@ -263,6 +268,14 @@ func newTbtcChain(
)
}

reservationRouter, err := reservationRouterBinding(bridgeAddress, baseChain)
if err != nil {
return nil, fmt.Errorf(
"failed to attach to ReservationRouter binding: [%v]",
err,
)
}

return &TbtcChain{
baseChain: baseChain,
bridge: bridge,
Expand All @@ -271,6 +284,7 @@ func newTbtcChain(
sortitionPool: sortitionPool,
walletProposalValidator: walletProposalValidator,
redemptionWatchtower: redemptionWatchtower,
reservationRouter: reservationRouter,
ecdsaDkgValidatorAddress: ecdsaDkgValidatorAddress,
sweptDepositsCache: cache.NewGenericTimeCache[*tbtc.DepositChainRequest](sweptDepositsCachePeriod),
}, nil
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[
{
"inputs": [
{
"internalType": "uint256",
"name": "depositKey",
"type": "uint256"
}
],
"name": "isReservedDeposit",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
}
]
88 changes: 87 additions & 1 deletion pkg/chain/ethereum/tbtc/gen/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
npm_package_name=@keep-network/tbtc-v2

# Contracts for which the bindings should be generated.
required_contracts := Bridge MaintainerProxy LightRelay LightRelayMaintainerProxy WalletProposalValidator RedemptionWatchtower
required_contracts := Bridge MaintainerProxy LightRelay LightRelayMaintainerProxy WalletProposalValidator RedemptionWatchtower ReservationRouter

# There is a bug in the currently used abigen version (v1.10.19) that makes it
# re-declaring structs used by multiple contracts
Expand All @@ -22,6 +22,7 @@ define after_abi_hook
$(eval type := $(1))
$(if $(filter $(type),WalletProposalValidator),$(call fix_wallet_proposal_validator_collision))
$(if $(filter $(type),MaintainerProxy),$(call fix_maintainer_proxy_collision))
$(if $(filter $(type),ReservationRouter),$(call fix_reservation_router_collision))
endef
define fix_wallet_proposal_validator_collision
@perl -pi -e s,BitcoinTxInfo,BitcoinTxInfo2,g ./abi/WalletProposalValidator.go
Expand All @@ -32,12 +33,26 @@ define fix_maintainer_proxy_collision
@perl -pi -e s,BitcoinTxProof,BitcoinTxProof2,g ./abi/MaintainerProxy.go
@perl -pi -e s,BitcoinTxInfo,BitcoinTxInfo3,g ./abi/MaintainerProxy.go
endef
# ReservationRouter introduces its own copies of the BitcoinTx.* structs
# (BitcoinTxInfo, BitcoinTxProof, BitcoinTxUTXO) used by submitReservationProof.
# These names already collide with Bridge's (BitcoinTxInfo/BitcoinTxProof/BitcoinTxUTXO),
# WalletProposalValidator's (BitcoinTxInfo2/BitcoinTxUTXO3), and MaintainerProxy's
# (BitcoinTxInfo3/BitcoinTxProof2/BitcoinTxUTXO2). Renumber ReservationRouter's
# copies to the next free suffix in each family. The router code only ever runs
# via Bridge.fallback delegatecall, so its storage pointer is unused; this is
# a purely textual rename to keep the abi package compiling.
define fix_reservation_router_collision
@perl -pi -e s,BitcoinTxInfo,BitcoinTxInfo4,g ./abi/ReservationRouter.go
@perl -pi -e s,BitcoinTxProof,BitcoinTxProof3,g ./abi/ReservationRouter.go
@perl -pi -e s,BitcoinTxUTXO,BitcoinTxUTXO4,g ./abi/ReservationRouter.go
endef

# See explanation in https://github.com/keep-network/keep-common/issues/117.
define after_contract_hook
$(eval type := $(1))
$(if $(filter $(type),WalletProposalValidator),$(call fix_wallet_proposal_validator_contract_collision))
$(if $(filter $(type),MaintainerProxy),$(call fix_maintainer_proxy_contract_collision))
$(if $(filter $(type),ReservationRouter),$(call fix_reservation_router_contract_collision))
endef
define fix_wallet_proposal_validator_contract_collision
@perl -pi -e s,BitcoinTxUTXO,BitcoinTxUTXO3,g ./contract/WalletProposalValidator.go
Expand All @@ -51,5 +66,76 @@ define fix_maintainer_proxy_contract_collision
@perl -pi -e s,BitcoinTxProof,BitcoinTxProof2,g ./cmd/MaintainerProxy.go
@perl -pi -e s,BitcoinTxInfo,BitcoinTxInfo3,g ./cmd/MaintainerProxy.go
endef
# keep-common's generator emits BitcoinTx* references inside the generated
# contract/cmd binding code paths too (e.g. method wrappers). Apply the same
# renames there so the contract and cmd packages compile.
define fix_reservation_router_contract_collision
@perl -pi -e s,BitcoinTxInfo,BitcoinTxInfo4,g ./contract/ReservationRouter.go
@perl -pi -e s,BitcoinTxProof,BitcoinTxProof3,g ./contract/ReservationRouter.go
@perl -pi -e s,BitcoinTxUTXO,BitcoinTxUTXO4,g ./contract/ReservationRouter.go
@perl -pi -e s,BitcoinTxInfo,BitcoinTxInfo4,g ./cmd/ReservationRouter.go
@perl -pi -e s,BitcoinTxProof,BitcoinTxProof3,g ./cmd/ReservationRouter.go
@perl -pi -e s,BitcoinTxUTXO,BitcoinTxUTXO4,g ./cmd/ReservationRouter.go
endef

include ../../common/gen/Makefile

# @keep-network/tbtc-v2@development on npm does not yet publish
# ReservationRouter.json (threshold-network/keep-core#4281), which makes
# `make generate` fail outright since nothing else can produce that
# prerequisite. Fall back to a vendored copy - its ABI is byte-for-byte
# the ABI already embedded in the committed bindings (re-derived from
# ReservationRouterMetaData.ABI, with the "struct"/"enum"/"contract"
# internalType prefix space abigen's metadata packer strips put back;
# verified by round-tripping through the same abigen + keep-common
# generator invocation and diffing byte-identical against
# abi/ReservationRouter.go, contract/ReservationRouter.go, and
# cmd/ReservationRouter.go) - only when the real artifact is missing,
# and only in the `development` environment, which already tolerates
# placeholder addresses (see the _address/% rule above). Non-development
# builds still hard-fail if the real artifact is ever missing there,
# since a real deployed address must never be substituted silently.
# Remove this rule once tbtc-v2 publishes the real artifact upstream.
${artifacts_dir}/ReservationRouter.json:
ifeq ($(environment), development)
@[ -f "$@" ] || { \
echo "ReservationRouter - artifact missing from ${npm_package_name}@${environment}, using vendored fallback (see threshold-network/keep-core#4281)"; \
cp ReservationRouter.fallback-artifact.json "$@"; \
}
else
@[ -f "$@" ] || { echo "$@ does not exist!"; exit 1; }
endif

# @keep-network/tbtc-v2@development on npm publishes Bridge.json and
# WalletProposalValidator.json, but both are stale relative to the
# reservation feature: they're missing isReservedDeposit (Bridge) and
# validateReservationAnchorProposal/validateReservationReanchorProposal
# (WalletProposalValidator), which the committed bindings already call
# (threshold-network/keep-core#4281). Unlike ReservationRouter.json,
# these files exist, so an only-if-missing artifact rule can't apply -
# patch the fetched artifact in place instead, merging in vendored
# fragments (extracted from the committed BridgeMetaData.ABI /
# WalletProposalValidatorMetaData.ABI, internalType prefix space
# restored the same way as ReservationRouter's; verified by
# round-tripping through the same abigen + keep-common generator
# invocation, producing a clean `go build ./...`) before anything reads
# the artifact. Only in `development`; only when the methods are
# actually missing, so a real future npm publish makes this a no-op
# without needing to be removed first. Non-development builds are
# untouched. Remove this whole block once tbtc-v2 publishes the real
# methods upstream.
.PHONY: patch-artifacts
check_artifacts: patch-artifacts
patch-artifacts:
ifeq ($(environment), development)
@jq -e '.abi[] | select(.name == "isReservedDeposit")' ${artifacts_dir}/Bridge.json >/dev/null 2>&1 || { \
echo "Bridge - artifact missing reservation methods, patching in vendored fallback (see threshold-network/keep-core#4281)"; \
jq --slurpfile extra Bridge.reservation-methods-fallback.json '.abi += $$extra[0]' ${artifacts_dir}/Bridge.json > ${artifacts_dir}/Bridge.json.patched && \
mv ${artifacts_dir}/Bridge.json.patched ${artifacts_dir}/Bridge.json; \
}
@jq -e '.abi[] | select(.name == "validateReservationAnchorProposal")' ${artifacts_dir}/WalletProposalValidator.json >/dev/null 2>&1 || { \
echo "WalletProposalValidator - artifact missing reservation methods, patching in vendored fallback (see threshold-network/keep-core#4281)"; \
jq --slurpfile extra WalletProposalValidator.reservation-methods-fallback.json '.abi += $$extra[0]' ${artifacts_dir}/WalletProposalValidator.json > ${artifacts_dir}/WalletProposalValidator.json.patched && \
mv ${artifacts_dir}/WalletProposalValidator.json.patched ${artifacts_dir}/WalletProposalValidator.json; \
}
endif
Loading
Loading