From 20f095a9008c1ae9e3eaa51bddcd6218040276a5 Mon Sep 17 00:00:00 2001 From: Niran Babalola Date: Tue, 9 Jun 2026 15:20:14 -0500 Subject: [PATCH] feat: configure flashblocks leeway time --- runner/benchmark/definition.go | 11 ++++++- runner/benchmark/definition_test.go | 26 +++++++++++++++ runner/clients/builder/client.go | 3 ++ runner/clients/types/types.go | 13 ++++---- runner/network/network_benchmark.go | 49 +++++++++++++++-------------- runner/service.go | 6 ++-- 6 files changed, 75 insertions(+), 33 deletions(-) create mode 100644 runner/benchmark/definition_test.go diff --git a/runner/benchmark/definition.go b/runner/benchmark/definition.go index 6e5decf..d017014 100644 --- a/runner/benchmark/definition.go +++ b/runner/benchmark/definition.go @@ -164,7 +164,8 @@ func (s SnapshotDefinition) CreateSnapshot(nodeType string, outputDir string) er // FlashblocksConfig holds top-level flashblocks configuration. type FlashblocksConfig struct { - BlockTime string `yaml:"block_time"` + BlockTime string `yaml:"block_time"` + LeewayTime string `yaml:"leeway_time"` } const DefaultFlashblocksBlockTime = "250" @@ -196,6 +197,14 @@ func (bc *BenchmarkConfig) FlashblocksBlockTime() string { return DefaultFlashblocksBlockTime } +// FlashblocksLeewayTime returns the configured flashblocks leeway time, if set. +func (bc *BenchmarkConfig) FlashblocksLeewayTime() string { + if bc.Flashblocks != nil && bc.Flashblocks.LeewayTime != "" { + return bc.Flashblocks.LeewayTime + } + return "" +} + type DatadirConfig struct { Sequencer *string `yaml:"sequencer"` Validator *string `yaml:"validator"` diff --git a/runner/benchmark/definition_test.go b/runner/benchmark/definition_test.go new file mode 100644 index 0000000..28e90d8 --- /dev/null +++ b/runner/benchmark/definition_test.go @@ -0,0 +1,26 @@ +package benchmark_test + +import ( + "testing" + + "github.com/base/base-bench/runner/benchmark" + "github.com/stretchr/testify/require" +) + +func TestFlashblocksLeewayTime(t *testing.T) { + t.Run("configured", func(t *testing.T) { + config := &benchmark.BenchmarkConfig{ + Flashblocks: &benchmark.FlashblocksConfig{ + LeewayTime: "300", + }, + } + + require.Equal(t, "300", config.FlashblocksLeewayTime()) + }) + + t.Run("default", func(t *testing.T) { + config := &benchmark.BenchmarkConfig{} + + require.Empty(t, config.FlashblocksLeewayTime()) + }) +} diff --git a/runner/clients/builder/client.go b/runner/clients/builder/client.go index 605f93e..6b59cd1 100644 --- a/runner/clients/builder/client.go +++ b/runner/clients/builder/client.go @@ -52,6 +52,9 @@ func (r *BuilderClient) Run(ctx context.Context, cfg *types.RuntimeConfig) error if cfg.FlashblocksBlockTime != "" { cfg2.Args = append(cfg2.Args, "--flashblocks.block-time", cfg.FlashblocksBlockTime) } + if cfg.FlashblocksLeewayTime != "" { + cfg2.Args = append(cfg2.Args, "--flashblocks.leeway-time", cfg.FlashblocksLeewayTime) + } if cfg.BlockTimeMs > 0 { cfg2.Args = append(cfg2.Args, "--rollup.chain-block-time", fmt.Sprintf("%d", cfg.BlockTimeMs)) } diff --git a/runner/clients/types/types.go b/runner/clients/types/types.go index c88b621..3346889 100644 --- a/runner/clients/types/types.go +++ b/runner/clients/types/types.go @@ -10,12 +10,13 @@ import ( ) type RuntimeConfig struct { - Stdout io.WriteCloser - Stderr io.WriteCloser - Args []string - FlashblocksURL *string // Optional URL for flashblocks websocket server (only used by clients that support it) - FlashblocksBlockTime string // Block time for flashblocks in milliseconds (e.g. "250") - BlockTimeMs uint64 // L2 block time in milliseconds + Stdout io.WriteCloser + Stderr io.WriteCloser + Args []string + FlashblocksURL *string // Optional URL for flashblocks websocket server (only used by clients that support it) + FlashblocksBlockTime string // Block time for flashblocks in milliseconds (e.g. "250") + FlashblocksLeewayTime string // Leeway time for flashblocks in milliseconds (e.g. "300") + BlockTimeMs uint64 // L2 block time in milliseconds } // ExecutionClient is an abstraction over the different clients that can be used to run the chain like diff --git a/runner/network/network_benchmark.go b/runner/network/network_benchmark.go index ac55845..a3d64fd 100644 --- a/runner/network/network_benchmark.go +++ b/runner/network/network_benchmark.go @@ -49,10 +49,11 @@ type NetworkBenchmark struct { testConfig *benchtypes.TestConfig proofConfig *benchmark.ProofProgramOptions - transactionPayload payload.Definition - ports portmanager.PortManager - mode benchmark.BenchmarkExecutionMode - flashblocksBlockTime string + transactionPayload payload.Definition + ports portmanager.PortManager + mode benchmark.BenchmarkExecutionMode + flashblocksBlockTime string + flashblocksLeewayTime string } // NewNetworkBenchmark creates a new network benchmark. @@ -60,7 +61,7 @@ type NetworkBenchmark struct { // The sequencer phase always runs and produces the payload stream. The // normalized execution mode only controls whether the validator phase is run // afterward to replay that stream. -func NewNetworkBenchmark(config *benchtypes.TestConfig, log log.Logger, sequencerOptions *config.InternalClientOptions, validatorOptions *config.InternalClientOptions, proofConfig *benchmark.ProofProgramOptions, transactionPayload payload.Definition, ports portmanager.PortManager, mode benchmark.BenchmarkExecutionMode, flashblocksBlockTime string) (*NetworkBenchmark, error) { +func NewNetworkBenchmark(config *benchtypes.TestConfig, log log.Logger, sequencerOptions *config.InternalClientOptions, validatorOptions *config.InternalClientOptions, proofConfig *benchmark.ProofProgramOptions, transactionPayload payload.Definition, ports portmanager.PortManager, mode benchmark.BenchmarkExecutionMode, flashblocksBlockTime string, flashblocksLeewayTime string) (*NetworkBenchmark, error) { if mode.RunValidator && validatorOptions == nil { return nil, errors.New("validator options are required when the validator role is enabled") } @@ -69,15 +70,16 @@ func NewNetworkBenchmark(config *benchtypes.TestConfig, log log.Logger, sequence } return &NetworkBenchmark{ - log: log, - sequencerOptions: sequencerOptions, - validatorOptions: validatorOptions, - testConfig: config, - proofConfig: proofConfig, - transactionPayload: transactionPayload, - ports: ports, - mode: mode, - flashblocksBlockTime: flashblocksBlockTime, + log: log, + sequencerOptions: sequencerOptions, + validatorOptions: validatorOptions, + testConfig: config, + proofConfig: proofConfig, + transactionPayload: transactionPayload, + ports: ports, + mode: mode, + flashblocksBlockTime: flashblocksBlockTime, + flashblocksLeewayTime: flashblocksLeewayTime, }, nil } @@ -114,7 +116,7 @@ func (nb *NetworkBenchmark) Run(ctx context.Context) error { } func (nb *NetworkBenchmark) benchmarkSequencer(ctx context.Context, l1Chain *l1Chain) (*benchtypes.PayloadResult, uint64, types.ExecutionClient, error) { - sequencerClient, err := setupNode(ctx, nb.log, nb.testConfig.Params.NodeType, nb.testConfig.Params, nb.sequencerOptions, nb.ports, "", nb.flashblocksBlockTime) + sequencerClient, err := setupNode(ctx, nb.log, nb.testConfig.Params.NodeType, nb.testConfig.Params, nb.sequencerOptions, nb.ports, "", nb.flashblocksBlockTime, nb.flashblocksLeewayTime) if err != nil { return nil, 0, nil, fmt.Errorf("failed to setup sequencer node: %w", err) } @@ -193,7 +195,7 @@ func (nb *NetworkBenchmark) benchmarkValidator(ctx context.Context, payloadResul validatorNodeType = nb.testConfig.Params.NodeType } - validatorClient, err := setupNode(ctx, nb.log, validatorNodeType, nb.testConfig.Params, nb.validatorOptions, nb.ports, flashblockServerURL, nb.flashblocksBlockTime) + validatorClient, err := setupNode(ctx, nb.log, validatorNodeType, nb.testConfig.Params, nb.validatorOptions, nb.ports, flashblockServerURL, nb.flashblocksBlockTime, nb.flashblocksLeewayTime) if err != nil { sequencerClient.Stop() return fmt.Errorf("failed to setup validator node: %w", err) @@ -312,7 +314,7 @@ func (nb *NetworkBenchmark) runsValidator() bool { return nb.mode.RunValidator } -func setupNode(ctx context.Context, l log.Logger, nodeTypeStr string, params benchtypes.RunParams, options *config.InternalClientOptions, portManager portmanager.PortManager, flashblockServerURL string, flashblocksBlockTime string) (types.ExecutionClient, error) { +func setupNode(ctx context.Context, l log.Logger, nodeTypeStr string, params benchtypes.RunParams, options *config.InternalClientOptions, portManager portmanager.PortManager, flashblockServerURL string, flashblocksBlockTime string, flashblocksLeewayTime string) (types.ExecutionClient, error) { if options == nil { return nil, errors.New("client options cannot be nil") } @@ -352,12 +354,13 @@ func setupNode(ctx context.Context, l log.Logger, nodeTypeStr string, params ben } runtimeConfig := &types.RuntimeConfig{ - Stdout: stdoutLogger, - Stderr: stderrLogger, - Args: args, - FlashblocksURL: flashblocksURLPtr, - FlashblocksBlockTime: flashblocksBlockTime, - BlockTimeMs: uint64(params.BlockTime.Milliseconds()), + Stdout: stdoutLogger, + Stderr: stderrLogger, + Args: args, + FlashblocksURL: flashblocksURLPtr, + FlashblocksBlockTime: flashblocksBlockTime, + FlashblocksLeewayTime: flashblocksLeewayTime, + BlockTimeMs: uint64(params.BlockTime.Milliseconds()), } if err := client.Run(ctx, runtimeConfig); err != nil { diff --git a/runner/service.go b/runner/service.go index 723e95b..f1b48f1 100644 --- a/runner/service.go +++ b/runner/service.go @@ -422,7 +422,7 @@ func (s *service) loadTestOutputPath(genesis *core.Genesis, transactionPayload p } } -func (s *service) runTest(ctx context.Context, params types.RunParams, workingDir string, outputDir string, snapshotConfig *benchmark.SnapshotDefinition, proofConfig *benchmark.ProofProgramOptions, transactionPayload payload.Definition, datadirsConfig *benchmark.DatadirConfig, mode benchmark.BenchmarkExecutionMode, flashblocksBlockTime string) (*benchmark.RunResult, error) { +func (s *service) runTest(ctx context.Context, params types.RunParams, workingDir string, outputDir string, snapshotConfig *benchmark.SnapshotDefinition, proofConfig *benchmark.ProofProgramOptions, transactionPayload payload.Definition, datadirsConfig *benchmark.DatadirConfig, mode benchmark.BenchmarkExecutionMode, flashblocksBlockTime string, flashblocksLeewayTime string) (*benchmark.RunResult, error) { s.log.Info(fmt.Sprintf("Running benchmark with params: %+v", params)) @@ -487,7 +487,7 @@ func (s *service) runTest(ctx context.Context, params types.RunParams, workingDi } // Run benchmark - benchmark, err := network.NewNetworkBenchmark(config, s.log, sequencerOptions, validatorOptions, proofConfig, transactionPayload, s.portState, mode, flashblocksBlockTime) + benchmark, err := network.NewNetworkBenchmark(config, s.log, sequencerOptions, validatorOptions, proofConfig, transactionPayload, s.portState, mode, flashblocksBlockTime, flashblocksLeewayTime) if err != nil { return nil, errors.Wrap(err, "failed to create network benchmark") } @@ -676,7 +676,7 @@ outerLoop: return errors.Wrap(err, "failed to create output directory") } - metricSummary, err := s.runTest(ctx, c.Params, s.config.DataDir(), outputDir, testPlan.Snapshot, testPlan.ProofProgram, transactionPayloads[c.Params.PayloadID], testPlan.Datadir, testPlan.Mode, config.FlashblocksBlockTime()) + metricSummary, err := s.runTest(ctx, c.Params, s.config.DataDir(), outputDir, testPlan.Snapshot, testPlan.ProofProgram, transactionPayloads[c.Params.PayloadID], testPlan.Datadir, testPlan.Mode, config.FlashblocksBlockTime(), config.FlashblocksLeewayTime()) if err != nil { log.Error("Failed to run test", "err", err) metricSummary = &benchmark.RunResult{