From 3b718ef2e0816a4c96edd6b483d93f99352650df Mon Sep 17 00:00:00 2001 From: skosito Date: Tue, 19 May 2026 19:13:41 +0200 Subject: [PATCH] fix(zetaclient): respect DisableTssBlockScan in Bitcoin observer (#4597) * fix(zetaclient): respect DisableTssBlockScan in Bitcoin observer * same fix in inbound tracker * log * changelog --- zetaclient/chains/bitcoin/observer/inbound.go | 8 ++++ .../chains/bitcoin/observer/inbound_test.go | 37 +++++++++++++++++++ .../bitcoin/observer/inbound_tracker.go | 12 ++++++ 3 files changed, 57 insertions(+) diff --git a/zetaclient/chains/bitcoin/observer/inbound.go b/zetaclient/chains/bitcoin/observer/inbound.go index 0cb57dab57..6109094154 100644 --- a/zetaclient/chains/bitcoin/observer/inbound.go +++ b/zetaclient/chains/bitcoin/observer/inbound.go @@ -28,6 +28,14 @@ func (ob *Observer) ObserveInbound(ctx context.Context) error { return err } + // Bitcoin's only inbound mechanism is direct transfers to the TSS address. + // When DisableTssBlockScan is true, skip all inbound scanning so new deposits + // are not observed (outbound/withdrawal processing is unaffected). + if ob.ChainParams().DisableTssBlockScan { + ob.Logger().Sampled.Info().Msg("skip inbound observation: DisableTssBlockScan is true") + return nil + } + // get fee rate multiplier feeRateMultiplier, err := ob.ChainParams().GasPriceMultiplier.Float64() if err != nil { diff --git a/zetaclient/chains/bitcoin/observer/inbound_test.go b/zetaclient/chains/bitcoin/observer/inbound_test.go index 70d31db1f3..baaed9e8a1 100644 --- a/zetaclient/chains/bitcoin/observer/inbound_test.go +++ b/zetaclient/chains/bitcoin/observer/inbound_test.go @@ -146,6 +146,43 @@ func TestAvgFeeRateBlock828440Errors(t *testing.T) { }) } +func Test_ObserveInbound_DisableTssBlockScan(t *testing.T) { + chain := chains.BitcoinMainnet + ob := newTestSuite(t, chain) + + // flip the chain param to disable inbound scanning + chainParams := ob.ChainParams() + chainParams.DisableTssBlockScan = true + ob.SetChainParams(chainParams) + + // ObserveInbound should return early without scanning any block. + // We intentionally do NOT mock GetBlockHash/GetBlockVerbose — if scanning + // were attempted, the mock client would fail the test on unexpected calls. + err := ob.ObserveInbound(ob.ctx) + require.NoError(t, err) +} + +func Test_ObserveInboundTrackers_DisableTssBlockScan(t *testing.T) { + chain := chains.BitcoinMainnet + ob := newTestSuite(t, chain) + + chainParams := ob.ChainParams() + chainParams.DisableTssBlockScan = true + ob.SetChainParams(chainParams) + + // Even with trackers present, observeInboundTrackers should return early. + // We intentionally do NOT mock GetRawTransactionVerbose/GetBlockVerbose — + // if processing were attempted, the mock client would fail on unexpected calls. + trackers := []crosschaintypes.InboundTracker{ + {ChainId: chain.ChainId, TxHash: "abc"}, + } + err := ob.observeInboundTrackers(ob.ctx, trackers, false) + require.NoError(t, err) + + err = ob.observeInboundTrackers(ob.ctx, trackers, true) + require.NoError(t, err) +} + func Test_GetInboundVoteFromBtcEvent(t *testing.T) { r := sample.Rand() diff --git a/zetaclient/chains/bitcoin/observer/inbound_tracker.go b/zetaclient/chains/bitcoin/observer/inbound_tracker.go index be18eb518c..d07fa817a1 100644 --- a/zetaclient/chains/bitcoin/observer/inbound_tracker.go +++ b/zetaclient/chains/bitcoin/observer/inbound_tracker.go @@ -43,6 +43,18 @@ func (ob *Observer) observeInboundTrackers( trackers []types.InboundTracker, isInternal bool, ) error { + // Bitcoin's only inbound mechanism is direct transfers to the TSS address. + // When DisableTssBlockScan is true, skip inbound tracker processing so new + // deposits referenced by external or internal trackers are not voted on + // (outbound/withdrawal processing is unaffected). + if ob.ChainParams().DisableTssBlockScan { + ob.Logger().Sampled.Info(). + Bool("is_internal", isInternal). + Int("tracker_count", len(trackers)). + Msg("skip inbound tracker processing: DisableTssBlockScan is true") + return nil + } + // take at most MaxInternalTrackersPerScan for each scan if len(trackers) > config.MaxInboundTrackersPerScan { trackers = trackers[:config.MaxInboundTrackersPerScan]