Skip to content

Coordination windows performance improvements#3864

Open
lrsaturnino wants to merge 4 commits intomainfrom
feature/deposit-sweep-bounded-lookback
Open

Coordination windows performance improvements#3864
lrsaturnino wants to merge 4 commits intomainfrom
feature/deposit-sweep-bounded-lookback

Conversation

@lrsaturnino
Copy link
Member

@lrsaturnino lrsaturnino commented Feb 13, 2026

Summary

  • FindDepositsToSweep now limits DepositRevealed event scanning to the most recent ~30 days (DepositSweepLookBackBlocks = 216000 blocks) instead of querying from block 0, significantly reducing RPC load on long-running nodes
  • Includes underflow protection: when currentBlock < 216000, filterStartBlock remains 0 to avoid uint64 wraparound
  • FindDeposits (used by the MovingFunds safety guard) continues to scan from block 0 to preserve full-history coverage for wallet safety checks
  • Unswept deposits are now grouped by vault address (case-insensitive) before sweep proposal; the largest group is selected to maximize per-transaction throughput, since deposits targeting different vaults cannot be swept together
  • Vault=0x0 (nil-vault) deposits excluded from the selected group are logged at Warn level for operator follow-up; they remain recoverable via later sweep cycles, depositor refunds, or reinitializer re-assignment
  • The Vault field is propagated through DepositReference and Deposit structs for downstream consumers
  • DepositSweep and MovedFundsSweep coordination actions switch from every 4th coordination window to every window at block 24559289 (~March 1st 2026); MovingFunds retains the 4th-window guard to avoid multiplying its full-history chain scan load

Coordination actions — before and after

Before:

Priority Action Frequency Lookback
0 ActionRedemption Every window Full history (block 0) — redemptionTimeout was ~20 years, exceeds chain height
1 ActionDepositSweep Every 4th window Full history (block 0)
2 ActionMovedFundsSweep Every 4th window Full history (block 0)
3 ActionMovingFunds Every 4th window Full history (block 0)
4 ActionHeartbeat 6.25% probability No chain scan

After (block >= 24559289):

Priority Action Frequency Lookback
0 ActionRedemption Every window 94,600 blocks (~13.14 days) — redemptionTimeout changed to 13 days on-chain
1 ActionDepositSweep Every window 216,000 blocks (~30 days)
2 ActionMovedFundsSweep Every window 216,000 blocks (~30 days)
3 ActionMovingFunds Every 4th window Full history (block 0)
4 ActionHeartbeat 6.25% probability No chain scan

Changes

Coordination layer (coordination.go):

  • Add exported DepositSweepEveryWindowActivationBlock constant set to block 24559289 (~March 1st 2026 00:00 UTC)
  • Add coordinationBlock parameter to getActionsChecklist
  • Before activation block: all three actions (DepositSweep, MovedFundsSweep, MovingFunds) gated to every 4th window
  • After activation block: DepositSweep and MovedFundsSweep run on every coordination window; MovingFunds stays gated to every 4th window to protect against excessive full-history scans

Coordination tests (coordination_test.go):

  • TestCoordinationExecutor_GetActionsChecklist covers pre-activation behavior (blocks below 24559289): non-4th windows get only Redemption, 4th windows get all actions
  • TestCoordinationExecutor_GetActionsChecklist_PostActivation covers post-activation behavior (blocks above 24559289) with safety invariant assertions
  • assertPostActivationSafety helper — verifies ActionRedemption at index 0, DepositSweep and MovedFundsSweep always present, MovingFunds absent on non-4th windows
  • assertChecklistOrdering helper — verifies canonical priority ordering across the checklist

Production code (deposit_sweep.go):

  • Add exported DepositSweepLookBackBlocks constant (216000 blocks, ~30 days at 12s/block)
  • Add filterStartBlock parameter to internal findDeposits() function
  • FindDepositsToSweep() computes bounded start block via BlockCounter.CurrentBlock() with underflow guard
  • FindDeposits() passes filterStartBlock=0 to preserve full-history behavior
  • Set DepositRevealedEventFilter.StartBlock from the computed value
  • Group unswept deposits by vault address with case-insensitive normalization
  • Select the largest vault group for sweep proposal (largest-group-first policy)
  • Log multi-group scenarios at Info level; log excluded nil-vault deposits at Warn level
  • Propagate Vault field through Deposit and DepositReference structs

Test helpers (tbtcpgtest.go):

  • Add Vault field to test Deposit struct and DepositsReferences() output

Tests (deposit_sweep_test.go):

  • Add TestDepositSweepLookBackBlocks — validates the constant equals 216000
  • Add TestDepositSweepTask_FindDepositsToSweep_BoundedLookback — exercises the bounded path with currentBlock=300000
  • Add TestDepositSweepTask_FindDepositsToSweep_UnderflowGuard — exercises the underflow path with currentBlock=100000
  • Wire MockBlockCounter into existing JSON-driven scenario tests
  • Add TestFindDepositsToSweep_VaultGrouping with 10 sub-tests covering nil vaults, mixed vaults, case normalization, tied groups, and multi-group selection

Test plan

  • go test ./pkg/tbtcpg/... -v — all tests pass
  • go test ./pkg/tbtc/... -run TestCoordinationExecutor_GetActionsChecklist -v — all coordination tests pass
  • go build ./pkg/... — compiles cleanly
  • go vet ./pkg/... — no new issues
  • Verify FindDeposits (MovingFunds path) still uses filterStartBlock=0
  • Vault grouping selects correct largest group in multi-vault scenarios
  • Nil-vault deposits are logged but not lost (recoverable paths documented)
  • Pre-activation: all three actions gated to every 4th window
  • Post-activation (block >= 24559289): DepositSweep and MovedFundsSweep on every window
  • Post-activation: MovingFunds remains gated to every 4th window
  • All operators must upgrade before block 24559289 (~March 1st 2026)

…ries

Add a configurable look-back period (DepositSweepLookBackBlocks = 216000
blocks, ~30 days) to FindDepositsToSweep so it only scans recent blocks
for DepositRevealed events instead of the full chain history. When the
current block exceeds the look-back window, filterStartBlock is computed
as currentBlock - lookBackBlocks; otherwise it falls back to 0 to guard
against underflow. FindDeposits (used by the MovingFunds safety guard)
continues to scan from block 0 to preserve full-history coverage.

Add tests for both the bounded lookback path (currentBlock=300000,
filterStartBlock=84000) and the underflow guard path
(currentBlock=100000, filterStartBlock=0). Wire MockBlockCounter into
the existing JSON-driven scenario tests so they pass with the new
BlockCounter dependency.
Deposits targeting different vaults cannot be swept in the same
transaction. This change groups unswept deposits by their vault
address (with case-insensitive normalization) and selects the
largest group to maximize per-transaction throughput.

Vault=0x0 (nil-vault) deposits that are not selected are logged
at Warn level for operator awareness, as they remain recoverable
via later sweep cycles, depositor refunds, or reinitializer
re-assignment.

Also propagates the Vault field through DepositReference and
Deposit structs so downstream consumers have access to it.
@lrsaturnino lrsaturnino changed the title Add bounded lookback window for deposit sweep event queries Deposit sweep performance and correctness improvements Feb 14, 2026
… sweeps

Introduce DepositSweepEveryWindowActivationBlock constant that controls
when DepositSweep and MovedFundsSweep actions switch from every 4th
coordination window to every window. MovingFunds retains the 4th-window
gate to avoid multiplying its full-history chain scan load.

The activation block is currently set to 0 (placeholder) and must be
replaced with the actual mainnet block height before release.

Update getActionsChecklist to accept coordinationBlock and branch on the
activation gate. Expand tests with post-activation safety invariants
and canonical ordering assertions.
Set DepositSweepEveryWindowActivationBlock to 24559289, the estimated
Ethereum block height for March 1st 00:00 UTC. Before this block, all
three actions (DepositSweep, MovedFundsSweep, MovingFunds) remain gated
to every 4th coordination window. After this block, DepositSweep and
MovedFundsSweep run on every window while MovingFunds stays gated.

Update tests to cover both pre-activation (low block numbers) and
post-activation (blocks above 24559289) code paths with correct
expected checklists for each regime.
@lrsaturnino lrsaturnino marked this pull request as ready for review February 14, 2026 06:44
@lrsaturnino lrsaturnino changed the title Deposit sweep performance and correctness improvements Coordination windows performance improvements Feb 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant