From 944349d79a313e1bf865c6d56947594264ff4a13 Mon Sep 17 00:00:00 2001 From: Shawn <44221603+shaspitz@users.noreply.github.com> Date: Tue, 1 Jul 2025 17:22:47 -0700 Subject: [PATCH 1/3] feat: block interval param for full bidder type --- tools/bidder-bot/main.go | 8 +++ tools/bidder-bot/notifier/full.go | 8 +++ tools/bidder-bot/notifier/full_test.go | 86 ++++++++++++++++++++++++++ tools/bidder-bot/service/service.go | 2 + 4 files changed, 104 insertions(+) diff --git a/tools/bidder-bot/main.go b/tools/bidder-bot/main.go index c9bcf6ec4..ee7644a6c 100644 --- a/tools/bidder-bot/main.go +++ b/tools/bidder-bot/main.go @@ -87,6 +87,13 @@ var ( Value: false, } + optionBlockInterval = &cli.Uint64Flag{ + Name: "block-interval", + Usage: "Only used for full notifier. Headers that are not a multiple of this interval will be skipped", + EnvVars: []string{"BLOCK_INTERVAL"}, + Value: 4, + } + optionCheckBalances = &cli.BoolFlag{ Name: "check-balances", Usage: "whether to periodically check account balances", @@ -225,6 +232,7 @@ func main() { L1WsUrls: c.StringSlice(optionL1WsUrls.Name), BeaconApiUrls: c.StringSlice(optionBeaconApiUrls.Name), IsFullNotifier: c.Bool(optionUseFullNotifier.Name), + BlockInterval: c.Uint64(optionBlockInterval.Name), Signer: signer, CheckBalances: c.Bool(optionCheckBalances.Name), } diff --git a/tools/bidder-bot/notifier/full.go b/tools/bidder-bot/notifier/full.go index 7be62db42..fcfd9de02 100644 --- a/tools/bidder-bot/notifier/full.go +++ b/tools/bidder-bot/notifier/full.go @@ -18,17 +18,20 @@ type FullNotifier struct { l1Client L1Client lastNotifiedBlockNum uint64 mu sync.Mutex + blockInterval uint64 } func NewFullNotifier( logger *slog.Logger, l1Client L1Client, targetBlockChan chan bidder.TargetBlock, + blockInterval uint64, ) *FullNotifier { return &FullNotifier{ logger: logger, l1Client: l1Client, targetBlockChan: targetBlockChan, + blockInterval: blockInterval, } } @@ -84,6 +87,11 @@ func (b *FullNotifier) handleHeader(ctx context.Context, header *types.Header) e "target_block_time", targetBlock.Time, ) + if header.Number.Uint64()%b.blockInterval != 0 { + b.logger.Debug("skipping header", "header_number", header.Number.Uint64()) + return nil + } + b.mu.Lock() defer b.mu.Unlock() diff --git a/tools/bidder-bot/notifier/full_test.go b/tools/bidder-bot/notifier/full_test.go index de28096ec..6f5888d51 100644 --- a/tools/bidder-bot/notifier/full_test.go +++ b/tools/bidder-bot/notifier/full_test.go @@ -4,6 +4,7 @@ import ( "context" "math/big" "os" + "slices" "strings" "testing" "time" @@ -52,6 +53,7 @@ func TestHandleHeader(t *testing.T) { logger, nil, targetBlockChan, + 1, // Setting block interval to 1 ensures no headers are skipped ) header := &types.Header{ Number: big.NewInt(int64(71)), @@ -89,6 +91,7 @@ func TestChannelTimeout(t *testing.T) { logger, nil, targetBlockChan, + 1, // Setting block interval to 1 ensures no headers are skipped ) err := notifier.HandleHeader(ctx, &types.Header{Number: big.NewInt(5)}) @@ -147,3 +150,86 @@ func TestChannelTimeout(t *testing.T) { default: } } + +func TestBlockInterval(t *testing.T) { + t.Parallel() + logger := util.NewTestLogger(os.Stdout) + + tests := []struct { + name string + blockInterval uint64 + headers []types.Header + expectedTargetBlocks []uint64 + }{ + { + name: "block interval 1, should receive all headers", + blockInterval: 1, + headers: []types.Header{ + {Number: big.NewInt(1)}, + {Number: big.NewInt(2)}, + {Number: big.NewInt(777)}, + {Number: big.NewInt(778)}, + }, + expectedTargetBlocks: []uint64{2, 3, 778, 779}, // target = header + 1 + }, + + { + name: "block interval 2, should receive 2nd, 4th, 444th headers", + blockInterval: 2, + headers: []types.Header{ + {Number: big.NewInt(1)}, + {Number: big.NewInt(2)}, + {Number: big.NewInt(3)}, + {Number: big.NewInt(4)}, + {Number: big.NewInt(444)}, + }, + expectedTargetBlocks: []uint64{3, 5, 445}, // target = header + 1 + }, + + { + name: "block interval 7, should receive 7th, 14th, 700th headers", + blockInterval: 7, + headers: []types.Header{ + {Number: big.NewInt(1)}, + {Number: big.NewInt(2)}, + {Number: big.NewInt(3)}, + {Number: big.NewInt(4)}, + {Number: big.NewInt(7)}, + {Number: big.NewInt(14)}, + {Number: big.NewInt(700)}, + {Number: big.NewInt(701)}, + }, + expectedTargetBlocks: []uint64{8, 15, 701}, // target = header + 1 + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + targetBlockChan := make(chan bidder.TargetBlock, len(test.headers)) + notifier := notifier.NewFullNotifier( + logger, + nil, + targetBlockChan, + test.blockInterval, + ) + for _, header := range test.headers { + err := notifier.HandleHeader(context.Background(), &header) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + } + receivedTargetBlocks := make([]uint64, 0, len(test.expectedTargetBlocks)) + for i := 0; i < len(test.expectedTargetBlocks); i++ { + select { + case targetBlock := <-targetBlockChan: + receivedTargetBlocks = append(receivedTargetBlocks, targetBlock.Num) + case <-time.After(1 * time.Second): + t.Fatal("timeout waiting for target block") + } + } + if !slices.Equal(receivedTargetBlocks, test.expectedTargetBlocks) { + t.Fatalf("expected to receive blocks %v, but got %v", test.expectedTargetBlocks, receivedTargetBlocks) + } + }) + } +} diff --git a/tools/bidder-bot/service/service.go b/tools/bidder-bot/service/service.go index f3c6b80bf..2a478a9c0 100644 --- a/tools/bidder-bot/service/service.go +++ b/tools/bidder-bot/service/service.go @@ -39,6 +39,7 @@ type Config struct { GasFeeCap *big.Int BidAmount *big.Int IsFullNotifier bool + BlockInterval uint64 CheckBalances bool } @@ -113,6 +114,7 @@ func New(config *Config) (*Service, error) { config.Logger.With("module", "full_notifier"), l1WsClient, targetBlockChan, // send-and-receive for draining capability + config.BlockInterval, ) } else { if len(config.BeaconApiUrls) == 0 { From ff0ca992c01c5d9625266648a5a26c495f2e3e0c Mon Sep 17 00:00:00 2001 From: Shawn <44221603+shaspitz@users.noreply.github.com> Date: Tue, 1 Jul 2025 17:30:12 -0700 Subject: [PATCH 2/3] nit --- tools/bidder-bot/notifier/full_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bidder-bot/notifier/full_test.go b/tools/bidder-bot/notifier/full_test.go index 6f5888d51..7f00dd4c5 100644 --- a/tools/bidder-bot/notifier/full_test.go +++ b/tools/bidder-bot/notifier/full_test.go @@ -219,7 +219,7 @@ func TestBlockInterval(t *testing.T) { } } receivedTargetBlocks := make([]uint64, 0, len(test.expectedTargetBlocks)) - for i := 0; i < len(test.expectedTargetBlocks); i++ { + for len(targetBlockChan) > 0 { select { case targetBlock := <-targetBlockChan: receivedTargetBlocks = append(receivedTargetBlocks, targetBlock.Num) From 010baf38c06dc4a6e52000aba42d17f8f58d1edb Mon Sep 17 00:00:00 2001 From: Shawn <44221603+shaspitz@users.noreply.github.com> Date: Tue, 1 Jul 2025 18:03:37 -0700 Subject: [PATCH 3/3] fix: register flag --- tools/bidder-bot/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/bidder-bot/main.go b/tools/bidder-bot/main.go index ee7644a6c..fe4259472 100644 --- a/tools/bidder-bot/main.go +++ b/tools/bidder-bot/main.go @@ -176,6 +176,7 @@ func main() { optionAutoDepositAmount, optionBidAmount, optionUseFullNotifier, + optionBlockInterval, optionCheckBalances, }, Action: func(c *cli.Context) error {