Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
134 commits
Select commit Hold shift + click to select a range
230e9b1
feat(tbtc): add covenant signer job substrate
mswilkison Mar 9, 2026
829e565
fix(tbtc): harden covenant signer substrate
mswilkison Mar 9, 2026
04dbf2e
feat(tbtc): validate migration destination reservation artifacts
mswilkison Mar 9, 2026
c926dac
test(tbtc): expand reservation artifact validation coverage
mswilkison Mar 9, 2026
b7cec76
feat(tbtc): validate covenant migration transaction plan
mswilkison Mar 9, 2026
d17f62c
docs(tbtc): note transaction-plan rollout dependency
mswilkison Mar 9, 2026
de399fa
feat(tbtc): implement self_v1 signer completion
mswilkison Mar 9, 2026
775162f
fix(tbtc): harden self_v1 signer validation
mswilkison Mar 9, 2026
3ee219f
fix(tbtc): repair covenant signer project branch CI
mswilkison Mar 9, 2026
08d6c2d
feat(tbtc): add qc_v1 signer handoff
mswilkison Mar 9, 2026
28551b7
test(tbtc): tighten qc_v1 handoff coverage
mswilkison Mar 9, 2026
a07d046
fix(tbtc): gofmt covenant signer
mswilkison Mar 9, 2026
d9ea0ca
Harden covenant signer service exposure
mswilkison Mar 9, 2026
c055799
Verify canonical migration plan commitments
mswilkison Mar 9, 2026
1f80606
Fix signer poll race and locktime bounds
mswilkison Mar 10, 2026
a3c8be0
Fix gosec G118 findings
mswilkison Mar 10, 2026
ee7212b
Harden covenant signer route controls
mswilkison Mar 10, 2026
effe86c
Validate role-tagged covenant approvals
mswilkison Mar 12, 2026
565b7ca
Normalize covenant signer request digests
mswilkison Mar 12, 2026
aa22d8c
Harden covenant signer request digests
mswilkison Mar 12, 2026
29813dd
Add covenant signer contract vectors
mswilkison Mar 12, 2026
f06a5f4
Add mixed-case covenant signer coverage
mswilkison Mar 12, 2026
790abb6
Verify depositor and custodian approval signatures
mswilkison Mar 12, 2026
635db6f
Clarify signer approval deferral and canonicalize commitment JSON
mswilkison Mar 12, 2026
31feaf2
Verify migration plan quotes in covenant signer
mswilkison Mar 13, 2026
cb8503b
Add migration plan quote verification vectors
mswilkison Mar 13, 2026
b9b8d77
Spike signer approval certificates
mswilkison Mar 13, 2026
5cb500c
Bind signer approval cert to on-chain wallet identity
mswilkison Mar 13, 2026
bcc4458
Verify structured covenant signer approvals
mswilkison Mar 13, 2026
3478202
Require structured signer approval on engine path
mswilkison Mar 13, 2026
594037f
Tighten signer approval cutover validation
mswilkison Mar 13, 2026
9753f7d
Warn on signer verifier-less startup
mswilkison Mar 13, 2026
1871c91
Remove legacy signer approval role path
mswilkison Mar 13, 2026
d9ad7c0
Harden signer approval verifier boundary
mswilkison Mar 13, 2026
9e50ed1
Pin covenant approval trust roots
mswilkison Mar 13, 2026
68f2325
Tighten covenant approval trust roots
mswilkison Mar 13, 2026
39ad0b1
Differentiate self_v1 presign and reconstruction requests
mswilkison Mar 13, 2026
e1b7614
Add self_v1 presign request vectors
mswilkison Mar 13, 2026
b96ec9b
Run gofmt on covenant signer files
mswilkison Mar 13, 2026
d9713a7
Require covenant approval trust roots in production mode
mswilkison Mar 14, 2026
5192f0d
fix(covenantsigner): add HTTP timeouts and body size cap
piotr-roslaniec Mar 16, 2026
20eaab9
fix(covenantsigner): set explicit max header size
piotr-roslaniec Mar 16, 2026
5ff6ef7
fix(tbtc): require signer set hash in certificate verification
piotr-roslaniec Mar 16, 2026
95ce7b0
fix(tbtc): canonicalize signer set hash payload JSON
piotr-roslaniec Mar 16, 2026
088c376
fix(bitcoin): guard tx output index bounds in getScript
piotr-roslaniec Mar 16, 2026
6a6fc2a
fix(tbtc): guard against empty witness stack
piotr-roslaniec Mar 16, 2026
c493a53
fix(covenantsigner): return 405 for poll path method mismatch
piotr-roslaniec Mar 16, 2026
d384a91
fix(covenantsigner): return generic JSON decode errors
piotr-roslaniec Mar 16, 2026
9fb6758
fix(covenantsigner): reject unknown JSON envelope fields
piotr-roslaniec Mar 16, 2026
c8e51ce
fix(covenantsigner): unescape poll request ID before slash validation
piotr-roslaniec Mar 16, 2026
bd0359a
fix(covenantsigner): validate facade and idempotency identifiers
piotr-roslaniec Mar 16, 2026
dce2d63
fix(covenantsigner): error on unsupported submit route
piotr-roslaniec Mar 16, 2026
26cfbc6
refactor(covenantsigner): replace variadic validation options with ex…
piotr-roslaniec Mar 16, 2026
7c10051
fix(covenantsigner): make store replacement write-first
piotr-roslaniec Mar 16, 2026
7afab2b
test: align unknown-field behavior and fix go1.24 fmt vet issue
piotr-roslaniec Mar 16, 2026
af10dec
chore: open follow-up branch for feat/psbt-covenant-final-project-pr
piotr-roslaniec Mar 16, 2026
bff56f5
ci(client): add race detector job for covenant signer and tbtc
piotr-roslaniec Mar 16, 2026
f5d5df5
test(covenantsigner): add HTTP boundary error matrix coverage
piotr-roslaniec Mar 16, 2026
2f571cb
test(covenantsigner): add store durability fault-injection coverage
piotr-roslaniec Mar 16, 2026
3c810f2
test(cmd): add fail-fast startup tests with injected init handles
piotr-roslaniec Mar 16, 2026
1c3c2cd
test(crypto): add negative parsing coverage for signer approvals and …
piotr-roslaniec Mar 16, 2026
005ef9b
ci(client): gate race checks on high-risk path changes
piotr-roslaniec Mar 16, 2026
ed47d11
test(tbtc): cover poll no-op and unsupported route transitions
piotr-roslaniec Mar 16, 2026
9f1352f
test(chain/ethereum): add tbtc contract config and wallet-state error…
piotr-roslaniec Mar 16, 2026
cebfcfb
test(fuzz): add decoder fuzz targets for signer validation paths
piotr-roslaniec Mar 16, 2026
ae2fe3f
test(covenantsigner): split store and server suites into thematic files
piotr-roslaniec Mar 16, 2026
93ae29a
ci(client): scope race checks to stable tbtc tests
piotr-roslaniec Mar 17, 2026
1e31823
fix(covenantsigner): parse UpdatedAt for store dedup ordering
piotr-roslaniec Mar 17, 2026
3f36415
fix(covenantsigner): reject trailing JSON tokens in decodeJSON
piotr-roslaniec Mar 17, 2026
b620240
fix(covenantsigner): decouple poll digest from trust-root drift
piotr-roslaniec Mar 17, 2026
5bde9c5
fix(tbtc): classify wallet-not-found errors with sentinel
piotr-roslaniec Mar 17, 2026
d21734b
refactor(tbtc): share covenant build-and-sign flow
piotr-roslaniec Mar 17, 2026
0f6b1bb
fix(tbtc): require active outpoint confirmation before signing
piotr-roslaniec Mar 17, 2026
c47812c
docs(tbtc): document uncompressed signer-approval key format
piotr-roslaniec Mar 17, 2026
61ecad1
refactor(cmd): inject start dependencies without mutable globals
piotr-roslaniec Mar 17, 2026
d1d0fac
fix(covenantsigner): require signer approval verifier in strict mode
piotr-roslaniec Mar 17, 2026
92c2e24
fix(covenantsigner): harden request dedupe and signature canonicaliza…
piotr-roslaniec Mar 17, 2026
4c83bf6
style(cmd): apply gofmt to start dependency wiring
piotr-roslaniec Mar 17, 2026
ad1e448
test(covenantsigner): stabilize invalid UpdatedAt assertion
piotr-roslaniec Mar 17, 2026
af45ea9
refactor(covenantsigner): extract shared marshalCanonicalJSON utility
lrsaturnino Mar 19, 2026
94f7f59
feat(covenantsigner): make active outpoint confirmations configurable
lrsaturnino Mar 19, 2026
ced0283
feat(covenantsigner): add exclusive file lock to prevent concurrent s…
lrsaturnino Mar 19, 2026
fb17c50
fix(covenantsigner): add domain separation to request digest
lrsaturnino Mar 19, 2026
89c6e6a
fix(covenantsigner): detach submit context from HTTP lifecycle
lrsaturnino Mar 19, 2026
5dbb546
test(canonicaljson): expand Marshal tests with struct input, determin…
lrsaturnino Mar 19, 2026
aaff2dd
test(tbtc): add deterministic key ordering test for QcV1 signer hando…
lrsaturnino Mar 19, 2026
45e851c
docs(covenantsigner): add deployment topology and coordination guide
lrsaturnino Mar 19, 2026
8c5b62e
feat(tbtc): add fault isolation for wallet registry and resilient sto…
lrsaturnino Apr 9, 2026
8ff750b
fix(tbtc): fail closed on store corruption
mswilkison Apr 9, 2026
02223fe
fix(covenantsigner): address store lock gosec findings
mswilkison Apr 9, 2026
abdc2fa
Revert "fix(covenantsigner): address store lock gosec findings"
lrsaturnino Apr 13, 2026
65280f9
fix(covenantsigner): suppress gosec false positives on store lock fil…
lrsaturnino Apr 13, 2026
235e8fd
fix: implement audit findings from consolidated review (#3935)
lrsaturnino Apr 16, 2026
7a4c534
chore: open follow-up branch for feat/psbt-covenant-final-project-pr
piotr-roslaniec Mar 16, 2026
943851e
fix(tbtc): add sentinel errors for missing wallet registry data
piotr-roslaniec Apr 9, 2026
18580b3
fix(covenantsigner): bound submit context with timeout and shutdown c…
piotr-roslaniec Apr 9, 2026
630fec5
fix(tbtc): correct keyStorePersistance typo to keyStorePersistence
piotr-roslaniec Apr 9, 2026
61c56af
docs(covenantsigner): clarify store deduplication strategy in load
piotr-roslaniec Apr 9, 2026
94c4e34
fix(ci): detect when race detector -run filter matches no tests
piotr-roslaniec Apr 9, 2026
ff85b3b
fix(covenantsigner): correct context preservation test to use service…
piotr-roslaniec Apr 9, 2026
42af6ed
fix(covenantsigner): clear route poison when a valid job loads for sa…
piotr-roslaniec Apr 9, 2026
dc61759
fix(covenantsigner): replace poison-route with hard-fail on corrupt p…
lrsaturnino Apr 13, 2026
b3c7dd1
fix(covenantsigner): suppress gosec false positives on store lock fil…
lrsaturnino Apr 13, 2026
86aa58c
fix(covenantsigner): move gosec G118 nosec annotation to goroutine de…
piotr-roslaniec Apr 14, 2026
98f6602
fix(cmd): auto-derive DataDir from storage dir when signer port is set
piotr-roslaniec Apr 10, 2026
743629d
fix(cmd): handle SIGINT/SIGTERM for graceful shutdown
piotr-roslaniec Apr 10, 2026
0ef62f0
fix(covenantsigner): evict stale byRequestID entry unconditionally on…
piotr-roslaniec Apr 10, 2026
43eb627
fix(covenantsigner): clear poisoned route key on successful Put
piotr-roslaniec Apr 10, 2026
c2017fb
fix(covenantsigner): trim whitespace from ReservationID in normalizeM…
piotr-roslaniec Apr 10, 2026
9a04646
fix(covenantsigner): normalize and validate migrationPlanQuoteTrustRo…
piotr-roslaniec Apr 10, 2026
f1352c4
fix(tbtc): enforce low-S normalization on signer approval certificate…
piotr-roslaniec Apr 10, 2026
8dca415
fix(covenantsigner): release file lock on NewService initialization f…
piotr-roslaniec Apr 10, 2026
ba8a5f2
docs(tbtc): document qcV1SignerHandoff as downstream handoff API schema
piotr-roslaniec Apr 10, 2026
3b5f9e0
docs(covenantsigner): document Engine interface nil-transition contract
piotr-roslaniec Apr 10, 2026
07196bc
fix(covenantsigner): reject trailing JSON tokens in strictUnmarshal
piotr-roslaniec Apr 10, 2026
e03b5dc
refactor(covenantsigner): unify depositor and custodian trust root no…
piotr-roslaniec Apr 10, 2026
7157957
fix(covenantsigner): fail startup when trust roots configured without…
piotr-roslaniec Apr 10, 2026
db69d9e
refactor(tbtc): extract shared resolveActiveUtxo helper from self_v1 …
piotr-roslaniec Apr 10, 2026
c94db7e
feat(covenantsigner): add token-bucket rate limiting to submit endpoints
piotr-roslaniec Apr 10, 2026
852afe7
refactor(covenantsigner): split monolithic validation.go into focused…
piotr-roslaniec Apr 10, 2026
384810e
fix(ci): suppress gosec false positives and handle cleanup errors in …
piotr-roslaniec Apr 10, 2026
69fdebd
fix(ci): move G118 nosec annotation to goroutine launch line
piotr-roslaniec Apr 10, 2026
2110110
fix(covenantsigner): add missing poisonedRoutes field to Store struct
piotr-roslaniec Apr 17, 2026
0287624
fix(covenantsigner): address deep audit findings P0-P3
piotr-roslaniec Apr 17, 2026
7773434
fix(covenantsigner): propagate block provider errors
piotr-roslaniec Apr 17, 2026
90bc2d6
fix(covenantsigner): flatten nested nil check in loadPollJob
piotr-roslaniec Apr 17, 2026
f47f7a9
fix(covenantsigner): remove unused poisonedRoutes scaffolding
piotr-roslaniec Apr 17, 2026
3855026
test(covenantsigner): add scriptedEngine verifier support and current…
Apr 17, 2026
7ae4b2d
fix(covenantsigner): return expiration error when verifier is nil
piotr-roslaniec Apr 17, 2026
b6b1aa4
test(covenantsigner): improve block provider test setup
piotr-roslaniec Apr 17, 2026
6d66c04
test(covenantsigner): decouple scriptedEngine from SignerApprovalVeri…
piotr-roslaniec Apr 20, 2026
b5c510b
chore(deps): run go mod tidy
lrsaturnino Apr 23, 2026
6af268d
fix: restore changes lost during rebase onto feat/psbt-covenant-final…
piotr-roslaniec May 23, 2026
558f4bc
fix: implement deep-audit findings for covenant signer (#3938)
piotr-roslaniec May 23, 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
42 changes: 42 additions & 0 deletions .github/workflows/client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,25 @@ jobs:
- './config/_electrum_urls/**'
- './pkg/bitcoin/electrum/**'

client-risk-detect-changes:
runs-on: ubuntu-latest
outputs:
path-filter: ${{ steps.filter.outputs.path-filter }}
steps:
- uses: actions/checkout@v4
if: github.event_name == 'pull_request'

- uses: dorny/paths-filter@v2
if: github.event_name == 'pull_request'
id: filter
with:
filters: |
path-filter:
- './pkg/covenantsigner/**'
- './pkg/tbtc/**'
- './pkg/chain/ethereum/**'
- './cmd/start.go'

client-build-test-publish:
needs: client-detect-changes
if: |
Expand Down Expand Up @@ -301,6 +320,29 @@ jobs:
install-go: false
checks: "-SA1019"

client-race:
needs: client-risk-detect-changes
if: |
github.event_name == 'push'
|| needs.client-risk-detect-changes.outputs.path-filter == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: "go.mod"
- name: Race detector (high-risk packages)
run: |
go test -race -timeout 20m ./pkg/covenantsigner
go test -race -timeout 20m -v ./pkg/tbtc \
-run '^(TestSignerApprovalCertificateSignerSetHashBindsOnChainWalletIdentityAndThreshold|TestValidateMigrationOutputValues_RejectsValuesExceedingInt64)$' \
-count=1 2>&1 | tee /tmp/race-output.txt
# Fail if the -run filter matched no tests (silent pass).
if ! grep -q '=== RUN' /tmp/race-output.txt; then
echo "ERROR: race detector -run filter matched no tests" >&2
exit 1
fi

client-integration-test:
needs: [electrum-integration-detect-changes, client-build-test-publish]
if: |
Expand Down
36 changes: 36 additions & 0 deletions cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/keep-network/keep-core/pkg/bitcoin/electrum"
chainEthereum "github.com/keep-network/keep-core/pkg/chain/ethereum"
"github.com/keep-network/keep-core/pkg/clientinfo"
"github.com/keep-network/keep-core/pkg/covenantsigner"
"github.com/keep-network/keep-core/pkg/maintainer/spv"
"github.com/keep-network/keep-core/pkg/net/libp2p"
"github.com/keep-network/keep-core/pkg/tbtc"
Expand Down Expand Up @@ -46,6 +47,8 @@ func initFlags(
initStorageFlags(cmd, cfg)
case config.ClientInfo:
initClientInfoFlags(cmd, cfg)
case config.CovenantSigner:
initCovenantSignerFlags(cmd, cfg)
case config.Tbtc:
initTbtcFlags(cmd, cfg)
case config.Maintainer:
Expand Down Expand Up @@ -310,6 +313,39 @@ func initTbtcFlags(cmd *cobra.Command, cfg *config.Config) {
)
}

func initCovenantSignerFlags(cmd *cobra.Command, cfg *config.Config) {
cmd.Flags().IntVar(
&cfg.CovenantSigner.Port,
"covenantSigner.port",
covenantsigner.Config{}.Port,
"Covenant signer provider HTTP server listening port. Zero disables the service.",
)
cmd.Flags().StringVar(
&cfg.CovenantSigner.ListenAddress,
"covenantSigner.listenAddress",
covenantsigner.DefaultListenAddress,
"Covenant signer provider HTTP listen address. Defaults to loopback-only.",
)
cmd.Flags().StringVar(
&cfg.CovenantSigner.AuthToken,
"covenantSigner.authToken",
covenantsigner.Config{}.AuthToken,
"Covenant signer provider static Bearer auth token. Required for non-loopback binds; prefer config file or env var over CLI in production.",
)
cmd.Flags().BoolVar(
&cfg.CovenantSigner.EnableSelfV1,
"covenantSigner.enableSelfV1",
false,
"Expose self_v1 covenant signer HTTP routes. Keep disabled for a qc_v1-first launch unless self_v1 is explicitly approved.",
)
cmd.Flags().BoolVar(
&cfg.CovenantSigner.RequireApprovalTrustRoots,
"covenantSigner.requireApprovalTrustRoots",
false,
"Fail startup when enabled covenant routes are missing route-level approval trust roots. Request-time validation still enforces exact reserve/network trust-root matches.",
)
}

// Initialize flags for Maintainer configuration.
func initMaintainerFlags(command *cobra.Command, cfg *config.Config) {
command.Flags().BoolVar(
Expand Down
36 changes: 36 additions & 0 deletions cmd/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
ethereumEcdsa "github.com/keep-network/keep-core/pkg/chain/ethereum/ecdsa/gen"
ethereumTbtc "github.com/keep-network/keep-core/pkg/chain/ethereum/tbtc/gen"
ethereumThreshold "github.com/keep-network/keep-core/pkg/chain/ethereum/threshold/gen"
"github.com/keep-network/keep-core/pkg/covenantsigner"
)

var cmdFlagsTests = map[string]struct {
Expand Down Expand Up @@ -190,6 +191,41 @@ var cmdFlagsTests = map[string]struct {
expectedValueFromFlag: 76 * time.Second,
defaultValue: 10 * time.Minute,
},
"covenantSigner.port": {
readValueFunc: func(c *config.Config) interface{} { return c.CovenantSigner.Port },
flagName: "--covenantSigner.port",
flagValue: "9711",
expectedValueFromFlag: 9711,
defaultValue: 0,
},
"covenantSigner.listenAddress": {
readValueFunc: func(c *config.Config) interface{} { return c.CovenantSigner.ListenAddress },
flagName: "--covenantSigner.listenAddress",
flagValue: "0.0.0.0",
expectedValueFromFlag: "0.0.0.0",
defaultValue: covenantsigner.DefaultListenAddress,
},
"covenantSigner.authToken": {
readValueFunc: func(c *config.Config) interface{} { return c.CovenantSigner.AuthToken },
flagName: "--covenantSigner.authToken",
flagValue: "secret-token",
expectedValueFromFlag: "secret-token",
defaultValue: "",
},
"covenantSigner.enableSelfV1": {
readValueFunc: func(c *config.Config) interface{} { return c.CovenantSigner.EnableSelfV1 },
flagName: "--covenantSigner.enableSelfV1",
flagValue: "",
expectedValueFromFlag: true,
defaultValue: false,
},
"covenantSigner.requireApprovalTrustRoots": {
readValueFunc: func(c *config.Config) interface{} { return c.CovenantSigner.RequireApprovalTrustRoots },
flagName: "--covenantSigner.requireApprovalTrustRoots",
flagValue: "",
expectedValueFromFlag: true,
defaultValue: false,
},
"tbtc.preParamsPoolSize": {
readValueFunc: func(c *config.Config) interface{} { return c.Tbtc.PreParamsPoolSize },
flagName: "--tbtc.preParamsPoolSize",
Expand Down
117 changes: 109 additions & 8 deletions cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ package cmd
import (
"context"
"fmt"
"os/signal"
"path/filepath"
"syscall"
"time"

commonEthereum "github.com/keep-network/keep-common/pkg/chain/ethereum"
"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"
"github.com/keep-network/keep-core/pkg/bitcoin/electrum"
"github.com/keep-network/keep-core/pkg/operator"
"github.com/keep-network/keep-core/pkg/storage"
Expand All @@ -17,9 +22,11 @@ import (

"github.com/keep-network/keep-core/config"
"github.com/keep-network/keep-core/pkg/beacon"
beaconchain "github.com/keep-network/keep-core/pkg/beacon/chain"
"github.com/keep-network/keep-core/pkg/chain"
"github.com/keep-network/keep-core/pkg/chain/ethereum"
"github.com/keep-network/keep-core/pkg/clientinfo"
"github.com/keep-network/keep-core/pkg/covenantsigner"
"github.com/keep-network/keep-core/pkg/firewall"
"github.com/keep-network/keep-core/pkg/generator"
"github.com/keep-network/keep-core/pkg/net"
Expand All @@ -45,6 +52,77 @@ var StartCommand = &cobra.Command{
},
}

type startDeps struct {
connectEthereum func(
ctx context.Context,
config commonEthereum.Config,
) (
*ethereum.BeaconChain,
*ethereum.TbtcChain,
chain.BlockCounter,
chain.Signing,
*operator.PrivateKey,
error,
)
connectElectrum func(
ctx context.Context,
config electrum.Config,
) (bitcoin.Chain, error)
initializeNetwork func(
ctx context.Context,
applications []firewall.Application,
operatorPrivateKey *operator.PrivateKey,
blockCounter chain.BlockCounter,
) (net.Provider, error)
initializePersistence func() (
beaconKeyStorePersistence persistence.ProtectedHandle,
tbtcKeyStorePersistence persistence.ProtectedHandle,
tbtcDataPersistence persistence.BasicHandle,
err error,
)
initializeBeacon func(
ctx context.Context,
chain beaconchain.Interface,
netProvider net.Provider,
keyStorePersistence persistence.ProtectedHandle,
scheduler *generator.Scheduler,
) error
initializeTbtc func(
ctx context.Context,
chain tbtc.Chain,
btcChain bitcoin.Chain,
netProvider net.Provider,
keyStorePersistence persistence.ProtectedHandle,
workPersistence persistence.BasicHandle,
scheduler *generator.Scheduler,
proposalGenerator tbtc.CoordinationProposalGenerator,
config tbtc.Config,
clientInfoRegistry *clientinfo.Registry,
perfMetrics *clientinfo.PerformanceMetrics,
minActiveOutpointConfirmations uint,
) (covenantsigner.Engine, error)
initializeSigner func(
ctx context.Context,
config covenantsigner.Config,
handle persistence.BasicHandle,
engine covenantsigner.Engine,
) (*covenantsigner.Server, bool, error)
startScheduler func() *generator.Scheduler
}

func defaultStartDeps() startDeps {
return startDeps{
connectEthereum: ethereum.Connect,
connectElectrum: electrum.Connect,
initializeNetwork: initializeNetwork,
initializePersistence: initializePersistence,
initializeBeacon: beacon.Initialize,
initializeTbtc: tbtc.Initialize,
initializeSigner: covenantsigner.Initialize,
startScheduler: generator.StartScheduler,
}
}

func init() {
initFlags(StartCommand, &configFilePath, clientConfig, config.StartCmdCategories...)

Expand All @@ -63,15 +141,20 @@ Environment variables:

// start starts a node
func start(cmd *cobra.Command) error {
ctx := context.Background()
return startWithDeps(cmd, defaultStartDeps())
}

func startWithDeps(cmd *cobra.Command, deps startDeps) error {
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()

beaconChain, tbtcChain, blockCounter, signing, operatorPrivateKey, err :=
ethereum.Connect(ctx, clientConfig.Ethereum)
deps.connectEthereum(ctx, clientConfig.Ethereum)
if err != nil {
return fmt.Errorf("error connecting to Ethereum node: [%v]", err)
}

netProvider, err := initializeNetwork(
netProvider, err := deps.initializeNetwork(
ctx,
[]firewall.Application{beaconChain, tbtcChain},
operatorPrivateKey,
Expand Down Expand Up @@ -110,20 +193,20 @@ func start(cmd *cobra.Command) error {
// Skip initialization for bootstrap nodes as they are only used for network
// discovery.
if !isBootstrap() {
btcChain, err := electrum.Connect(ctx, clientConfig.Bitcoin.Electrum)
btcChain, err := deps.connectElectrum(ctx, clientConfig.Bitcoin.Electrum)
if err != nil {
return fmt.Errorf("could not connect to Electrum chain: [%v]", err)
}

beaconKeyStorePersistence,
tbtcKeyStorePersistence,
tbtcDataPersistence,
err := initializePersistence()
err := deps.initializePersistence()
if err != nil {
return fmt.Errorf("cannot initialize persistence: [%w]", err)
}

scheduler := generator.StartScheduler()
scheduler := deps.startScheduler()

if clientInfoRegistry != nil {
clientInfoRegistry.ObserveBtcConnectivity(
Expand All @@ -142,7 +225,7 @@ func start(cmd *cobra.Command) error {
rpcHealthChecker.Start(ctx)
}

err = beacon.Initialize(
err = deps.initializeBeacon(
ctx,
beaconChain,
netProvider,
Expand All @@ -158,7 +241,7 @@ func start(cmd *cobra.Command) error {
btcChain,
)

err = tbtc.Initialize(
covenantSignerEngine, err := deps.initializeTbtc(
ctx,
tbtcChain,
btcChain,
Expand All @@ -170,10 +253,28 @@ func start(cmd *cobra.Command) error {
clientConfig.Tbtc,
clientInfoRegistry,
perfMetrics, // Pass the existing performance metrics instance to avoid duplicate registrations
clientConfig.CovenantSigner.MinActiveOutpointConfirmations,
)
if err != nil {
return fmt.Errorf("error initializing TBTC: [%v]", err)
}

signerConfig := clientConfig.CovenantSigner
if signerConfig.DataDir == "" && signerConfig.Port != 0 {
signerConfig.DataDir = filepath.Join(
filepath.Clean(clientConfig.Storage.Dir), "work", "tbtc",
)
}

_, _, err = deps.initializeSigner(
ctx,
signerConfig,
tbtcDataPersistence,
covenantSignerEngine,
)
if err != nil {
return fmt.Errorf("error initializing covenant signer: [%v]", err)
}
}

nodeHeader(
Expand Down
Loading
Loading