From 35db44b9e3acc1bee93d56ba3b06aad72911d92a Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 11:09:50 -0700 Subject: [PATCH 01/15] feat: add load-test payload worker for base-load-test binary integration Add a new payload worker type 'load-test' that integrates the Rust base-load-test binary as an external transaction generator. The worker follows the same proxy-based pattern as the tx-fuzz integration: - New LoadTestPayloadWorker spawns the binary with a generated YAML config pointing to a proxy server that captures transactions - CLI flag --load-test-bin (env: BASE_BENCH_LOAD_TEST_BIN) for binary path - Config interface extended with LoadTestBinary() method - Factory routes 'load-test' payload type to the new worker - Generated config supports configurable sender_count, target_gps, and duration via YAML payload params --- benchmark/flags/flags.go | 32 ++-- runner/config/config.go | 55 +++--- runner/payload/factory.go | 10 ++ runner/payload/loadtest/load_test_worker.go | 183 ++++++++++++++++++++ 4 files changed, 245 insertions(+), 35 deletions(-) create mode 100644 runner/payload/loadtest/load_test_worker.go diff --git a/benchmark/flags/flags.go b/benchmark/flags/flags.go index 8f86508b..368ab569 100644 --- a/benchmark/flags/flags.go +++ b/benchmark/flags/flags.go @@ -15,22 +15,24 @@ func prefixEnvVars(name string) []string { } const ( - ConfigFlagName = "config" - RootDirFlagName = "root-dir" - OutputDirFlagName = "output-dir" - TxFuzzBinFlagName = "tx-fuzz-bin" - ProxyPortFlagName = "proxy-port" - BenchmarkRunIDFlagName = "benchmark-run-id" - MachineTypeFlagName = "machine-type" - MachineProviderFlagName = "machine-provider" - MachineRegionFlagName = "machine-region" - FileSystemFlagName = "file-system" + ConfigFlagName = "config" + RootDirFlagName = "root-dir" + OutputDirFlagName = "output-dir" + TxFuzzBinFlagName = "tx-fuzz-bin" + LoadTestBinFlagName = "load-test-bin" + ProxyPortFlagName = "proxy-port" + BenchmarkRunIDFlagName = "benchmark-run-id" + MachineTypeFlagName = "machine-type" + MachineProviderFlagName = "machine-provider" + MachineRegionFlagName = "machine-region" + FileSystemFlagName = "file-system" ParallelTxBatchesFlagName = "parallel-tx-batches" ) // TxFuzz defaults const ( - DefaultTxFuzzBin = "../tx-fuzz/cmd/livefuzzer/livefuzzer" + DefaultTxFuzzBin = "../tx-fuzz/cmd/livefuzzer/livefuzzer" + DefaultLoadTestBin = "./base-load-test" ) var ( @@ -62,6 +64,13 @@ var ( EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "TX_FUZZ_BIN"), } + LoadTestBinFlag = &cli.StringFlag{ + Name: LoadTestBinFlagName, + Usage: "Load test binary path", + Value: DefaultLoadTestBin, + EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "LOAD_TEST_BIN"), + } + ProxyPortFlag = &cli.IntFlag{ Name: "proxy-port", Usage: "Proxy port", @@ -116,6 +125,7 @@ var RunFlags = []cli.Flag{ RootDirFlag, OutputDirFlag, TxFuzzBinFlag, + LoadTestBinFlag, ProxyPortFlag, BenchmarkRunIDFlag, MachineTypeFlag, diff --git a/runner/config/config.go b/runner/config/config.go index c2890c42..0386f86f 100644 --- a/runner/config/config.go +++ b/runner/config/config.go @@ -20,6 +20,7 @@ type Config interface { DataDir() string OutputDir() string TxFuzzBinary() string + LoadTestBinary() string ProxyPort() int BenchmarkRunID() string MachineType() string @@ -30,36 +31,38 @@ type Config interface { } type config struct { - logConfig oplog.CLIConfig - configPath string - dataDir string - outputDir string - clientOptions ClientOptions - txFuzzBinary string - proxyPort int - benchmarkRunID string - machineType string - machineProvider string - machineRegion string - fileSystem string + logConfig oplog.CLIConfig + configPath string + dataDir string + outputDir string + clientOptions ClientOptions + txFuzzBinary string + loadTestBinary string + proxyPort int + benchmarkRunID string + machineType string + machineProvider string + machineRegion string + fileSystem string parallelTxBatches int } func NewConfig(ctx *cli.Context) Config { return &config{ - logConfig: oplog.ReadCLIConfig(ctx), - configPath: ctx.String(appFlags.ConfigFlagName), - dataDir: ctx.String(appFlags.RootDirFlagName), - outputDir: ctx.String(appFlags.OutputDirFlagName), - txFuzzBinary: ctx.String(appFlags.TxFuzzBinFlagName), - proxyPort: ctx.Int(appFlags.ProxyPortFlagName), - benchmarkRunID: ctx.String(appFlags.BenchmarkRunIDFlagName), - machineType: ctx.String(appFlags.MachineTypeFlagName), - machineProvider: ctx.String(appFlags.MachineProviderFlagName), - machineRegion: ctx.String(appFlags.MachineRegionFlagName), - fileSystem: ctx.String(appFlags.FileSystemFlagName), + logConfig: oplog.ReadCLIConfig(ctx), + configPath: ctx.String(appFlags.ConfigFlagName), + dataDir: ctx.String(appFlags.RootDirFlagName), + outputDir: ctx.String(appFlags.OutputDirFlagName), + txFuzzBinary: ctx.String(appFlags.TxFuzzBinFlagName), + loadTestBinary: ctx.String(appFlags.LoadTestBinFlagName), + proxyPort: ctx.Int(appFlags.ProxyPortFlagName), + benchmarkRunID: ctx.String(appFlags.BenchmarkRunIDFlagName), + machineType: ctx.String(appFlags.MachineTypeFlagName), + machineProvider: ctx.String(appFlags.MachineProviderFlagName), + machineRegion: ctx.String(appFlags.MachineRegionFlagName), + fileSystem: ctx.String(appFlags.FileSystemFlagName), parallelTxBatches: ctx.Int(appFlags.ParallelTxBatchesFlagName), - clientOptions: ReadClientOptions(ctx), + clientOptions: ReadClientOptions(ctx), } } @@ -112,6 +115,10 @@ func (c *config) TxFuzzBinary() string { return c.txFuzzBinary } +func (c *config) LoadTestBinary() string { + return c.loadTestBinary +} + func (c *config) BenchmarkRunID() string { return c.benchmarkRunID } diff --git a/runner/payload/factory.go b/runner/payload/factory.go index dd1d3102..dd621a99 100644 --- a/runner/payload/factory.go +++ b/runner/payload/factory.go @@ -7,6 +7,7 @@ import ( clienttypes "github.com/base/base-bench/runner/clients/types" benchtypes "github.com/base/base-bench/runner/network/types" "github.com/base/base-bench/runner/payload/contract" + "github.com/base/base-bench/runner/payload/loadtest" "github.com/base/base-bench/runner/payload/simulator" "github.com/base/base-bench/runner/payload/transferonly" "github.com/base/base-bench/runner/payload/txfuzz" @@ -31,6 +32,13 @@ func NewPayloadWorker(ctx context.Context, log log.Logger, testConfig *benchtype case "tx-fuzz": worker, err = txfuzz.NewTxFuzzPayloadWorker( log, sequencerClient.ClientURL(), params, privateKey, amount, config.TxFuzzBinary(), genesis.Config.ChainID) + case "load-test": + def, _ := definition.Params.(*loadtest.LoadTestPayloadDefinition) + if def == nil { + def = &loadtest.LoadTestPayloadDefinition{} + } + worker, err = loadtest.NewLoadTestPayloadWorker( + log, sequencerClient.ClientURL(), params, privateKey, amount, config.LoadTestBinary(), genesis.Config.ChainID, *def) case "transfer-only": worker, err = transferonly.NewTransferPayloadWorker( ctx, log, sequencerClient.ClientURL(), params, privateKey, amount, &genesis, definition.Params) @@ -77,6 +85,8 @@ func (t *Definition) UnmarshalYAML(node *yaml.Node) error { params = &transferonly.TransferOnlyPayloadDefinition{} case "tx-fuzz": params = &txfuzz.TxFuzzPayloadDefinition{} + case "load-test": + params = &loadtest.LoadTestPayloadDefinition{} case "contract": params = &contract.ContractPayloadDefinition{} case "simulator": diff --git a/runner/payload/loadtest/load_test_worker.go b/runner/payload/loadtest/load_test_worker.go new file mode 100644 index 00000000..58fb7527 --- /dev/null +++ b/runner/payload/loadtest/load_test_worker.go @@ -0,0 +1,183 @@ +package loadtest + +import ( + "context" + "crypto/ecdsa" + "encoding/hex" + "fmt" + "math/big" + "os" + "os/exec" + + "github.com/base/base-bench/runner/clients/common/proxy" + "github.com/base/base-bench/runner/network/mempool" + "github.com/base/base-bench/runner/network/types" + "github.com/base/base-bench/runner/payload/worker" + "github.com/ethereum/go-ethereum/log" + "github.com/pkg/errors" + "gopkg.in/yaml.v3" +) + +const proxyPort = 8545 + +// LoadTestPayloadDefinition is the YAML payload params for the load-test type. +type LoadTestPayloadDefinition struct { + SenderCount uint64 `yaml:"sender_count"` + TargetGPS uint64 `yaml:"target_gps"` + Duration string `yaml:"duration"` +} + +// loadTestConfig is the YAML config written to a temp file for the load-test binary. +type loadTestConfig struct { + RPC string `yaml:"rpc"` + SenderCount uint64 `yaml:"sender_count"` + TargetGPS uint64 `yaml:"target_gps"` + Duration string `yaml:"duration"` + Seed uint64 `yaml:"seed"` + FundingAmount string `yaml:"funding_amount"` + Transactions []loadTestTransactionDef `yaml:"transactions"` +} + +type loadTestTransactionDef struct { + Type string `yaml:"type"` + Weight uint64 `yaml:"weight"` +} + +type loadTestPayloadWorker struct { + log log.Logger + prefundSK string + loadTestBin string + elRPCURL string + gasLimit uint64 + params LoadTestPayloadDefinition + mempool *mempool.StaticWorkloadMempool + proxyServer *proxy.ProxyServer + configFilePath string +} + +// NewLoadTestPayloadWorker creates a worker that runs the base-load-test binary +// as an external transaction generator, capturing transactions via a proxy server. +func NewLoadTestPayloadWorker( + log log.Logger, + elRPCURL string, + params types.RunParams, + prefundedPrivateKey ecdsa.PrivateKey, + prefundAmount *big.Int, + loadTestBin string, + chainID *big.Int, + definition LoadTestPayloadDefinition, +) (worker.Worker, error) { + mp := mempool.NewStaticWorkloadMempool(log, chainID) + ps := proxy.NewProxyServer(elRPCURL, log, proxyPort, mp) + + w := &loadTestPayloadWorker{ + log: log, + prefundSK: hex.EncodeToString(prefundedPrivateKey.D.Bytes()), + loadTestBin: loadTestBin, + elRPCURL: elRPCURL, + gasLimit: params.GasLimit, + params: definition, + mempool: mp, + proxyServer: ps, + } + + return w, nil +} + +func (w *loadTestPayloadWorker) Mempool() mempool.FakeMempool { + return w.mempool +} + +func (w *loadTestPayloadWorker) Setup(ctx context.Context) error { + if err := w.proxyServer.Run(ctx); err != nil { + return errors.Wrap(err, "failed to run proxy server") + } + + configPath, err := w.writeConfig() + if err != nil { + return errors.Wrap(err, "failed to write load-test config") + } + w.configFilePath = configPath + + w.log.Info("Starting load test", "binary", w.loadTestBin, "config", configPath) + + cmd := exec.CommandContext(ctx, w.loadTestBin, configPath) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + cmd.Env = append(os.Environ(), fmt.Sprintf("FUNDER_KEY=%s", w.prefundSK)) + + if err := cmd.Start(); err != nil { + return errors.Wrap(err, "failed to start load test binary") + } + + return nil +} + +func (w *loadTestPayloadWorker) Stop(ctx context.Context) error { + w.proxyServer.Stop() + + if w.configFilePath != "" { + os.Remove(w.configFilePath) + } + + return nil +} + +func (w *loadTestPayloadWorker) SendTxs(ctx context.Context) error { + w.log.Info("Collecting txs from load test") + pendingTxs := w.proxyServer.PendingTxs() + w.proxyServer.ClearPendingTxs() + + w.mempool.AddTransactions(pendingTxs) + return nil +} + +// writeConfig generates a temporary YAML config file for the load-test binary +// with the RPC URL pointing to the proxy server. +func (w *loadTestPayloadWorker) writeConfig() (string, error) { + senderCount := w.params.SenderCount + if senderCount == 0 { + senderCount = 10 + } + + targetGPS := w.params.TargetGPS + if targetGPS == 0 { + targetGPS = w.gasLimit / 2 + } + + duration := w.params.Duration + if duration == "" { + duration = "600s" + } + + config := loadTestConfig{ + RPC: fmt.Sprintf("http://localhost:%d", proxyPort), + SenderCount: senderCount, + TargetGPS: targetGPS, + Duration: duration, + Seed: 12345, + FundingAmount: "10000000000000000000", + Transactions: []loadTestTransactionDef{ + {Type: "transfer", Weight: 70}, + {Type: "calldata", Weight: 20}, + {Type: "precompile", Weight: 10}, + }, + } + + data, err := yaml.Marshal(&config) + if err != nil { + return "", errors.Wrap(err, "failed to marshal load-test config") + } + + tmpFile, err := os.CreateTemp("", "load-test-config-*.yaml") + if err != nil { + return "", errors.Wrap(err, "failed to create temp config file") + } + defer tmpFile.Close() + + if _, err := tmpFile.Write(data); err != nil { + return "", errors.Wrap(err, "failed to write temp config file") + } + + return tmpFile.Name(), nil +} From 39fbbe58e0cd57795e88e8b6f1d9f51f856abc0a Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 11:26:40 -0700 Subject: [PATCH 02/15] fix: use UnmarshalBinary for typed transaction decoding in proxy The proxy server used rlp.DecodeBytes to decode captured transactions, which only handles legacy transactions. Typed transactions (EIP-2718, e.g. EIP-1559 type 2) have a type prefix byte before the RLP payload that causes rlp.DecodeBytes to fail with 'typed transaction too short'. Switch to Transaction.UnmarshalBinary() which handles both legacy and typed transaction formats. Also fix load-test worker config to include required fields for calldata (max_size) and precompile (target) transaction types. --- runner/clients/common/proxy/proxy.go | 9 +++++---- runner/payload/loadtest/load_test_worker.go | 10 ++++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/runner/clients/common/proxy/proxy.go b/runner/clients/common/proxy/proxy.go index 3da48b7d..f261c39e 100644 --- a/runner/clients/common/proxy/proxy.go +++ b/runner/clients/common/proxy/proxy.go @@ -22,7 +22,6 @@ import ( "github.com/ethereum/go-ethereum/common" ethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" ) type ProxyServer struct { @@ -196,11 +195,13 @@ func (p *ProxyServer) OverrideRequest(method string, rawParams json.RawMessage) return false, nil, fmt.Errorf("failed to decode hex: %w", err) } - err = rlp.DecodeBytes(rawTxBytes, &tx) + // Use UnmarshalBinary to support both legacy and typed (EIP-2718) transactions. + // The previous rlp.DecodeBytes only handled legacy transactions. + err = tx.UnmarshalBinary(rawTxBytes) if err != nil { - p.log.Error("failed to decode RLP", "err", err) - return false, nil, fmt.Errorf("failed to decode RLP: %w", err) + p.log.Error("failed to decode transaction", "err", err) + return false, nil, fmt.Errorf("failed to decode transaction: %w", err) } p.pendingTxs = append(p.pendingTxs, &tx) diff --git a/runner/payload/loadtest/load_test_worker.go b/runner/payload/loadtest/load_test_worker.go index 58fb7527..9c9bd42f 100644 --- a/runner/payload/loadtest/load_test_worker.go +++ b/runner/payload/loadtest/load_test_worker.go @@ -39,8 +39,10 @@ type loadTestConfig struct { } type loadTestTransactionDef struct { - Type string `yaml:"type"` - Weight uint64 `yaml:"weight"` + Type string `yaml:"type"` + Weight uint64 `yaml:"weight"` + MaxSize uint64 `yaml:"max_size,omitempty"` + Target string `yaml:"target,omitempty"` } type loadTestPayloadWorker struct { @@ -159,8 +161,8 @@ func (w *loadTestPayloadWorker) writeConfig() (string, error) { FundingAmount: "10000000000000000000", Transactions: []loadTestTransactionDef{ {Type: "transfer", Weight: 70}, - {Type: "calldata", Weight: 20}, - {Type: "precompile", Weight: 10}, + {Type: "calldata", Weight: 20, MaxSize: 256}, + {Type: "precompile", Weight: 10, Target: "sha256"}, }, } From 884b02ca975a1de59ef039dd3e1fdce0de7e3730 Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 11:36:09 -0700 Subject: [PATCH 03/15] fix: handle errcheck lint errors in load-test worker --- runner/payload/loadtest/load_test_worker.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/runner/payload/loadtest/load_test_worker.go b/runner/payload/loadtest/load_test_worker.go index 9c9bd42f..6e4ea769 100644 --- a/runner/payload/loadtest/load_test_worker.go +++ b/runner/payload/loadtest/load_test_worker.go @@ -119,7 +119,9 @@ func (w *loadTestPayloadWorker) Stop(ctx context.Context) error { w.proxyServer.Stop() if w.configFilePath != "" { - os.Remove(w.configFilePath) + if err := os.Remove(w.configFilePath); err != nil { + w.log.Warn("failed to remove load-test config", "path", w.configFilePath, "err", err) + } } return nil @@ -175,11 +177,15 @@ func (w *loadTestPayloadWorker) writeConfig() (string, error) { if err != nil { return "", errors.Wrap(err, "failed to create temp config file") } - defer tmpFile.Close() if _, err := tmpFile.Write(data); err != nil { + tmpFile.Close() return "", errors.Wrap(err, "failed to write temp config file") } + if err := tmpFile.Close(); err != nil { + return "", errors.Wrap(err, "failed to close temp config file") + } + return tmpFile.Name(), nil } From 61936602cf21e3bf75c737a21ca0949dc50b386b Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 11:42:35 -0700 Subject: [PATCH 04/15] feat: integrate load-test config into benchmark payload definition - sender_count and transactions passed from benchmark YAML payload params - target_gps computed from gas_limit / block_time (no hardcoding) - seed randomized using crypto/rand - duration set to 99999s (process killed on Stop) - Stop() kills the load-test process and reaps it - transactions YAML passed through as raw yaml.Node to support the full Rust config schema (transfer, calldata, precompile, erc20, etc.) --- runner/payload/loadtest/load_test_worker.go | 134 ++++++++++++++------ 1 file changed, 95 insertions(+), 39 deletions(-) diff --git a/runner/payload/loadtest/load_test_worker.go b/runner/payload/loadtest/load_test_worker.go index 6e4ea769..aad1edf5 100644 --- a/runner/payload/loadtest/load_test_worker.go +++ b/runner/payload/loadtest/load_test_worker.go @@ -3,6 +3,7 @@ package loadtest import ( "context" "crypto/ecdsa" + cryptorand "crypto/rand" "encoding/hex" "fmt" "math/big" @@ -21,28 +22,24 @@ import ( const proxyPort = 8545 // LoadTestPayloadDefinition is the YAML payload params for the load-test type. +// Fields map directly to the Rust base-load-test config format. +// The `transactions` field is passed through as raw YAML to support the full +// Rust config schema (transfer, calldata, precompile, erc20, etc.). type LoadTestPayloadDefinition struct { - SenderCount uint64 `yaml:"sender_count"` - TargetGPS uint64 `yaml:"target_gps"` - Duration string `yaml:"duration"` + SenderCount uint64 `yaml:"sender_count"` + FundingAmount string `yaml:"funding_amount"` + Transactions yaml.Node `yaml:"transactions"` } // loadTestConfig is the YAML config written to a temp file for the load-test binary. type loadTestConfig struct { - RPC string `yaml:"rpc"` - SenderCount uint64 `yaml:"sender_count"` - TargetGPS uint64 `yaml:"target_gps"` - Duration string `yaml:"duration"` - Seed uint64 `yaml:"seed"` - FundingAmount string `yaml:"funding_amount"` - Transactions []loadTestTransactionDef `yaml:"transactions"` -} - -type loadTestTransactionDef struct { - Type string `yaml:"type"` - Weight uint64 `yaml:"weight"` - MaxSize uint64 `yaml:"max_size,omitempty"` - Target string `yaml:"target,omitempty"` + RPC string `yaml:"rpc"` + SenderCount uint64 `yaml:"sender_count"` + TargetGPS uint64 `yaml:"target_gps"` + Duration string `yaml:"duration"` + Seed uint64 `yaml:"seed"` + FundingAmount string `yaml:"funding_amount"` + Transactions yaml.Node `yaml:"transactions"` } type loadTestPayloadWorker struct { @@ -51,9 +48,11 @@ type loadTestPayloadWorker struct { loadTestBin string elRPCURL string gasLimit uint64 + blockTimeSec uint64 params LoadTestPayloadDefinition mempool *mempool.StaticWorkloadMempool proxyServer *proxy.ProxyServer + cmd *exec.Cmd configFilePath string } @@ -72,15 +71,21 @@ func NewLoadTestPayloadWorker( mp := mempool.NewStaticWorkloadMempool(log, chainID) ps := proxy.NewProxyServer(elRPCURL, log, proxyPort, mp) + blockTimeSec := uint64(params.BlockTime.Seconds()) + if blockTimeSec == 0 { + blockTimeSec = 1 + } + w := &loadTestPayloadWorker{ - log: log, - prefundSK: hex.EncodeToString(prefundedPrivateKey.D.Bytes()), - loadTestBin: loadTestBin, - elRPCURL: elRPCURL, - gasLimit: params.GasLimit, - params: definition, - mempool: mp, - proxyServer: ps, + log: log, + prefundSK: hex.EncodeToString(prefundedPrivateKey.D.Bytes()), + loadTestBin: loadTestBin, + elRPCURL: elRPCURL, + gasLimit: params.GasLimit, + blockTimeSec: blockTimeSec, + params: definition, + mempool: mp, + proxyServer: ps, } return w, nil @@ -111,11 +116,22 @@ func (w *loadTestPayloadWorker) Setup(ctx context.Context) error { if err := cmd.Start(); err != nil { return errors.Wrap(err, "failed to start load test binary") } + w.cmd = cmd return nil } func (w *loadTestPayloadWorker) Stop(ctx context.Context) error { + if w.cmd != nil && w.cmd.Process != nil { + w.log.Info("Stopping load test process", "pid", w.cmd.Process.Pid) + if err := w.cmd.Process.Kill(); err != nil { + w.log.Warn("failed to kill load test process", "err", err) + } else { + // Reap the process to avoid zombies. + _, _ = w.cmd.Process.Wait() + } + } + w.proxyServer.Stop() if w.configFilePath != "" { @@ -136,6 +152,40 @@ func (w *loadTestPayloadWorker) SendTxs(ctx context.Context) error { return nil } +// defaultTransactions returns the default transaction mix as a yaml.Node. +func defaultTransactions() yaml.Node { + var node yaml.Node + // Default: 70% transfer, 20% calldata, 10% precompile + defaultYAML := ` +- weight: 70 + type: transfer +- weight: 20 + type: calldata + max_size: 256 +- weight: 10 + type: precompile + target: sha256 +` + if err := yaml.Unmarshal([]byte(defaultYAML), &node); err != nil { + panic(fmt.Sprintf("failed to parse default transactions YAML: %v", err)) + } + // yaml.Unmarshal wraps in a document node; return the inner sequence + if node.Kind == yaml.DocumentNode && len(node.Content) > 0 { + return *node.Content[0] + } + return node +} + +// randomSeed returns a cryptographically random uint64 seed. +func randomSeed() uint64 { + var b [8]byte + if _, err := cryptorand.Read(b[:]); err != nil { + return 42 + } + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 +} + // writeConfig generates a temporary YAML config file for the load-test binary // with the RPC URL pointing to the proxy server. func (w *loadTestPayloadWorker) writeConfig() (string, error) { @@ -144,28 +194,27 @@ func (w *loadTestPayloadWorker) writeConfig() (string, error) { senderCount = 10 } - targetGPS := w.params.TargetGPS - if targetGPS == 0 { - targetGPS = w.gasLimit / 2 + fundingAmount := w.params.FundingAmount + if fundingAmount == "" { + fundingAmount = "10000000000000000000" } - duration := w.params.Duration - if duration == "" { - duration = "600s" + // Compute target GPS from gas limit and block time + targetGPS := w.gasLimit / w.blockTimeSec + + transactions := w.params.Transactions + if transactions.Kind == 0 { + transactions = defaultTransactions() } config := loadTestConfig{ RPC: fmt.Sprintf("http://localhost:%d", proxyPort), SenderCount: senderCount, TargetGPS: targetGPS, - Duration: duration, - Seed: 12345, - FundingAmount: "10000000000000000000", - Transactions: []loadTestTransactionDef{ - {Type: "transfer", Weight: 70}, - {Type: "calldata", Weight: 20, MaxSize: 256}, - {Type: "precompile", Weight: 10, Target: "sha256"}, - }, + Duration: "99999s", + Seed: randomSeed(), + FundingAmount: fundingAmount, + Transactions: transactions, } data, err := yaml.Marshal(&config) @@ -187,5 +236,12 @@ func (w *loadTestPayloadWorker) writeConfig() (string, error) { return "", errors.Wrap(err, "failed to close temp config file") } + w.log.Info("Generated load-test config", + "sender_count", senderCount, + "target_gps", targetGPS, + "gas_limit", w.gasLimit, + "block_time_sec", w.blockTimeSec, + ) + return tmpFile.Name(), nil } From 01d084df234b932d82f38c79c71b41e4d702b016 Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 11:46:48 -0700 Subject: [PATCH 05/15] fix: reduce gzip noise in proxy DebugResponse DebugResponse unconditionally tried gzip decompression on every proxied response, logging at Error level when it failed. Most responses are plain JSON (not gzip-compressed), causing hundreds of spurious error lines per second. Fall back to logging the raw body at Debug level when the response is not gzip-encoded. --- runner/clients/common/proxy/proxy.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/runner/clients/common/proxy/proxy.go b/runner/clients/common/proxy/proxy.go index f261c39e..290e6fc4 100644 --- a/runner/clients/common/proxy/proxy.go +++ b/runner/clients/common/proxy/proxy.go @@ -218,21 +218,21 @@ func (p *ProxyServer) DebugResponse(method string, params json.RawMessage, respB p.log.Debug("method", "method", method) p.log.Debug("params", "params", params) + // Try gzip decompression; fall back to raw body if the response is plain JSON. gzipReader, err := gzip.NewReader(bytes.NewReader(respBody)) if err != nil { - p.log.Error("Error creating gzip reader", "err", err) + p.log.Debug("Response body", "body", string(respBody)) return } defer func() { if err := gzipReader.Close(); err != nil { - p.log.Error("Error closing gzip reader", "err", err) + p.log.Debug("Error closing gzip reader", "err", err) } }() uncompressedBody, err := io.ReadAll(gzipReader) - if err != nil { - p.log.Error("Error reading uncompressed response body", "err", err) + p.log.Debug("Error reading uncompressed response body", "err", err) return } p.log.Debug("Uncompressed body", "body", string(uncompressedBody)) From ed5fbe84d29e6b3c3fe45ef6b3395375f77b9036 Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 11:48:31 -0700 Subject: [PATCH 06/15] Revert "fix: reduce gzip noise in proxy DebugResponse" This reverts commit 01d084df234b932d82f38c79c71b41e4d702b016. --- runner/clients/common/proxy/proxy.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/runner/clients/common/proxy/proxy.go b/runner/clients/common/proxy/proxy.go index 290e6fc4..f261c39e 100644 --- a/runner/clients/common/proxy/proxy.go +++ b/runner/clients/common/proxy/proxy.go @@ -218,21 +218,21 @@ func (p *ProxyServer) DebugResponse(method string, params json.RawMessage, respB p.log.Debug("method", "method", method) p.log.Debug("params", "params", params) - // Try gzip decompression; fall back to raw body if the response is plain JSON. gzipReader, err := gzip.NewReader(bytes.NewReader(respBody)) if err != nil { - p.log.Debug("Response body", "body", string(respBody)) + p.log.Error("Error creating gzip reader", "err", err) return } defer func() { if err := gzipReader.Close(); err != nil { - p.log.Debug("Error closing gzip reader", "err", err) + p.log.Error("Error closing gzip reader", "err", err) } }() uncompressedBody, err := io.ReadAll(gzipReader) + if err != nil { - p.log.Debug("Error reading uncompressed response body", "err", err) + p.log.Error("Error reading uncompressed response body", "err", err) return } p.log.Debug("Uncompressed body", "body", string(uncompressedBody)) From 2cd345ca28128848855d585189daf66716241a67 Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 11:51:14 -0700 Subject: [PATCH 07/15] fix: suppress errcheck lint for tmpFile.Close in error path --- runner/payload/loadtest/load_test_worker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runner/payload/loadtest/load_test_worker.go b/runner/payload/loadtest/load_test_worker.go index aad1edf5..5ea9f1cf 100644 --- a/runner/payload/loadtest/load_test_worker.go +++ b/runner/payload/loadtest/load_test_worker.go @@ -228,7 +228,7 @@ func (w *loadTestPayloadWorker) writeConfig() (string, error) { } if _, err := tmpFile.Write(data); err != nil { - tmpFile.Close() + _ = tmpFile.Close() return "", errors.Wrap(err, "failed to write temp config file") } From 174a912307bf1d67e386adb2d3b2c19b3d6d4c6d Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 12:04:28 -0700 Subject: [PATCH 08/15] feat: add load-test CI workflow and example config - Add load-test.yaml workflow: triggers on PR and workflow_dispatch, builds binaries via _build-binaries.yaml, runs load-test benchmark, builds report, uploads output and report artifacts (always, even on failure) - Update _build-binaries.yaml to build and upload base-load-test artifact alongside base-reth-node and builder - Update build-base-reth-node.sh to also build base-load-test binary - Add configs/examples/load-test.yml benchmark config (10 senders, 70% transfer / 20% calldata / 10% precompile, 10 blocks, 1B gas) --- .github/workflows/_build-binaries.yaml | 12 +++- .github/workflows/load-test.yaml | 98 ++++++++++++++++++++++++++ clients/build-base-reth-node.sh | 15 ++-- configs/examples/load-test.yml | 29 ++++++++ 4 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/load-test.yaml create mode 100644 configs/examples/load-test.yml diff --git a/.github/workflows/_build-binaries.yaml b/.github/workflows/_build-binaries.yaml index a7bf7e5f..8e51c395 100644 --- a/.github/workflows/_build-binaries.yaml +++ b/.github/workflows/_build-binaries.yaml @@ -163,9 +163,10 @@ jobs: path: | ~/bin/base-reth-node ~/bin/builder - key: ${{ runner.os }}-base-reth-node-builder-${{ inputs.base_reth_node_version }} + ~/bin/base-load-test + key: ${{ runner.os }}-base-reth-node-builder-load-test-${{ inputs.base_reth_node_version }} - - name: Build base-reth-node and base-builder + - name: Build base-reth-node, base-builder, and base-load-test if: steps.cache-base-reth-node.outputs.cache-hit != 'true' run: | unset CI @@ -188,6 +189,13 @@ jobs: path: ~/bin/builder retention-days: 1 + - name: Upload base-load-test artifact + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: base-load-test + path: ~/bin/base-load-test + retention-days: 1 + build-op-program: runs-on: ubuntu-latest permissions: diff --git a/.github/workflows/load-test.yaml b/.github/workflows/load-test.yaml new file mode 100644 index 00000000..096015a5 --- /dev/null +++ b/.github/workflows/load-test.yaml @@ -0,0 +1,98 @@ +name: Load Test + +on: + pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + build-binaries: + name: Build binaries + uses: ./.github/workflows/_build-binaries.yaml + with: + base_reth_node_version: main + + load-test: + name: Run load test benchmark + runs-on: ubuntu-latest + needs: [build-binaries] + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + with: + egress-policy: audit + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Set up Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + + - name: Download base-reth-node + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + with: + name: base-reth-node + path: ${{ runner.temp }}/bin/ + + - name: Download builder + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + with: + name: builder + path: ${{ runner.temp }}/bin/ + + - name: Download base-load-test + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + with: + name: base-load-test + path: ${{ runner.temp }}/bin/ + + - name: Make binaries executable + run: chmod +x ${{ runner.temp }}/bin/* + + - name: Run load test benchmark + run: | + mkdir -p ${{ runner.temp }}/data-dir + mkdir -p ${{ runner.temp }}/output + + go run benchmark/cmd/main.go \ + --log.level info \ + run \ + --config configs/examples/load-test.yml \ + --root-dir ${{ runner.temp }}/data-dir \ + --output-dir ${{ runner.temp }}/output \ + --builder-bin ${{ runner.temp }}/bin/builder \ + --base-reth-node-bin ${{ runner.temp }}/bin/base-reth-node \ + --load-test-bin ${{ runner.temp }}/bin/base-load-test + + - name: Setup Node.js + if: always() + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "20" + + - name: Build Report + if: always() + run: | + cp -r ${{ runner.temp }}/output/ ./output/ || true + pushd report + npm install + npm run build + popd + + - name: Upload Output + if: always() + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: load-test-output + path: ${{ runner.temp }}/output/ + retention-days: 7 + + - name: Upload Report + if: always() + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: load-test-report + path: report/dist/ + retention-days: 7 diff --git a/clients/build-base-reth-node.sh b/clients/build-base-reth-node.sh index 98d030bb..9eeb61f0 100755 --- a/clients/build-base-reth-node.sh +++ b/clients/build-base-reth-node.sh @@ -13,7 +13,7 @@ BASE_RETH_NODE_VERSION="${BASE_RETH_NODE_VERSION:-main}" BUILD_DIR="${BUILD_DIR:-./build}" OUTPUT_DIR="${OUTPUT_DIR:-../bin}" -echo "Building base-reth-node and base-builder binaries..." +echo "Building base-reth-node, base-builder, and base-load-test binaries..." echo "Repository: $BASE_RETH_NODE_REPO" echo "Version/Commit: $BASE_RETH_NODE_VERSION" echo "Build directory: $BUILD_DIR" @@ -43,9 +43,9 @@ echo "Checking out version: $BASE_RETH_NODE_VERSION" git checkout -f "$BASE_RETH_NODE_VERSION" # Build the binaries using cargo -echo "Building base-reth-node and base-builder with cargo..." +echo "Building base-reth-node, base-builder, and base-load-test with cargo..." # Build with maxperf profile -cargo build --bin base-reth-node --bin base-builder --profile maxperf +cargo build --bin base-reth-node --bin base-builder --bin base-load-test --profile maxperf # Copy binaries to output directory echo "Copying binaries to output directory..." @@ -74,4 +74,11 @@ else exit 1 fi -echo "base-reth-node and base-builder binaries built successfully and placed in $FINAL_OUTPUT_DIR/" +if [ -f "target/maxperf/base-load-test" ]; then + cp target/maxperf/base-load-test "$FINAL_OUTPUT_DIR/" +else + echo "No base-load-test binary found" + exit 1 +fi + +echo "base-reth-node, base-builder, and base-load-test binaries built successfully and placed in $FINAL_OUTPUT_DIR/" diff --git a/configs/examples/load-test.yml b/configs/examples/load-test.yml new file mode 100644 index 00000000..6743ca60 --- /dev/null +++ b/configs/examples/load-test.yml @@ -0,0 +1,29 @@ +name: Load test throughput test +description: Test builder throughput using base-load-test binary as transaction generator +payloads: + - name: Load Test + type: load-test + id: load-test + sender_count: 10 + transactions: + - weight: 70 + type: transfer + - weight: 20 + type: calldata + max_size: 256 + - weight: 10 + type: precompile + target: sha256 + +benchmarks: + - variables: + - type: payload + value: load-test + - type: node_type + value: builder + - type: validator_node_type + value: base-reth-node + - type: num_blocks + value: 10 + - type: gas_limit + value: 1000000000 From 714dca3eebef55061917aa78cdd50969dcde9bf0 Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 12:09:24 -0700 Subject: [PATCH 09/15] fix: point load-test workflow at feature branch for base-load-test binary --- .github/workflows/load-test.yaml | 2 +- clients/build-base-reth-node.sh | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/load-test.yaml b/.github/workflows/load-test.yaml index 096015a5..9edace1e 100644 --- a/.github/workflows/load-test.yaml +++ b/.github/workflows/load-test.yaml @@ -13,7 +13,7 @@ jobs: name: Build binaries uses: ./.github/workflows/_build-binaries.yaml with: - base_reth_node_version: main + base_reth_node_version: feature/load-test-benchmark load-test: name: Run load test benchmark diff --git a/clients/build-base-reth-node.sh b/clients/build-base-reth-node.sh index 9eeb61f0..04380062 100755 --- a/clients/build-base-reth-node.sh +++ b/clients/build-base-reth-node.sh @@ -44,7 +44,6 @@ git checkout -f "$BASE_RETH_NODE_VERSION" # Build the binaries using cargo echo "Building base-reth-node, base-builder, and base-load-test with cargo..." -# Build with maxperf profile cargo build --bin base-reth-node --bin base-builder --bin base-load-test --profile maxperf # Copy binaries to output directory From c6b342ca2b0786756193117e28c8fba51dc08fb3 Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 12:19:04 -0700 Subject: [PATCH 10/15] fix: point all workflows at base repo SHA with base-load-test binary Both examples.yaml and load-test.yaml now use the same base repo SHA (38de4e038) which has the base-load-test binary target. The shared _build-binaries.yaml and build script build all three binaries. --- .github/workflows/examples.yaml | 2 +- .github/workflows/load-test.yaml | 2 +- clients/build-base-reth-node.sh | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/examples.yaml b/.github/workflows/examples.yaml index 1a7c75eb..d7cf0596 100644 --- a/.github/workflows/examples.yaml +++ b/.github/workflows/examples.yaml @@ -18,7 +18,7 @@ jobs: with: optimism_version: 3019251e80aa248e91743addd3e833190acb26f1 geth_version: 6cbfcd5161083bcd4052edc3022d9f99c6fe40e0 - base_reth_node_version: main + base_reth_node_version: 38de4e038 example-benchmarks: runs-on: ubuntu-latest diff --git a/.github/workflows/load-test.yaml b/.github/workflows/load-test.yaml index 9edace1e..4dc9d85e 100644 --- a/.github/workflows/load-test.yaml +++ b/.github/workflows/load-test.yaml @@ -13,7 +13,7 @@ jobs: name: Build binaries uses: ./.github/workflows/_build-binaries.yaml with: - base_reth_node_version: feature/load-test-benchmark + base_reth_node_version: 38de4e038 load-test: name: Run load test benchmark diff --git a/clients/build-base-reth-node.sh b/clients/build-base-reth-node.sh index 04380062..ab0bd852 100755 --- a/clients/build-base-reth-node.sh +++ b/clients/build-base-reth-node.sh @@ -13,7 +13,7 @@ BASE_RETH_NODE_VERSION="${BASE_RETH_NODE_VERSION:-main}" BUILD_DIR="${BUILD_DIR:-./build}" OUTPUT_DIR="${OUTPUT_DIR:-../bin}" -echo "Building base-reth-node, base-builder, and base-load-test binaries..." +echo "Building base-reth-node and base-builder binaries..." echo "Repository: $BASE_RETH_NODE_REPO" echo "Version/Commit: $BASE_RETH_NODE_VERSION" echo "Build directory: $BUILD_DIR" @@ -80,4 +80,4 @@ else exit 1 fi -echo "base-reth-node, base-builder, and base-load-test binaries built successfully and placed in $FINAL_OUTPUT_DIR/" +echo "Binaries built successfully and placed in $FINAL_OUTPUT_DIR/" From b42da26d4b1aedb8160226472fe24f0ad1e798cf Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 12:33:24 -0700 Subject: [PATCH 11/15] fix: disable Rust toolchain cache in _build-binaries setup-rust-toolchain runs cargo metadata to compute a cache key, but the benchmark repo has no Cargo.toml (it's Go). This causes exit code 101. Disable the built-in cache since we use our own actions/cache step for the built binaries. --- .github/workflows/_build-binaries.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/_build-binaries.yaml b/.github/workflows/_build-binaries.yaml index 8e51c395..0a9accc8 100644 --- a/.github/workflows/_build-binaries.yaml +++ b/.github/workflows/_build-binaries.yaml @@ -155,6 +155,8 @@ jobs: - name: Set up Rust uses: actions-rust-lang/setup-rust-toolchain@9399c7bb15d4c7d47b27263d024f0a4978346ba4 # v1.11.0 + with: + cache: false - name: Cache base-reth-node binaries uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # v3.4.3 From 86d1fde34df08d5178e792517631f4c1e4fb2713 Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 14:08:10 -0700 Subject: [PATCH 12/15] fix: use branch name for base repo checkout and fetch remote refs The short SHA was not fetchable because git clone only fetches the default branch. Use the branch name instead and add a fetch of the specific ref before checkout to handle both branch names and SHAs. --- .github/workflows/examples.yaml | 2 +- .github/workflows/load-test.yaml | 2 +- clients/build-base-reth-node.sh | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/examples.yaml b/.github/workflows/examples.yaml index d7cf0596..1656537a 100644 --- a/.github/workflows/examples.yaml +++ b/.github/workflows/examples.yaml @@ -18,7 +18,7 @@ jobs: with: optimism_version: 3019251e80aa248e91743addd3e833190acb26f1 geth_version: 6cbfcd5161083bcd4052edc3022d9f99c6fe40e0 - base_reth_node_version: 38de4e038 + base_reth_node_version: feature/load-test-benchmark example-benchmarks: runs-on: ubuntu-latest diff --git a/.github/workflows/load-test.yaml b/.github/workflows/load-test.yaml index 4dc9d85e..9edace1e 100644 --- a/.github/workflows/load-test.yaml +++ b/.github/workflows/load-test.yaml @@ -13,7 +13,7 @@ jobs: name: Build binaries uses: ./.github/workflows/_build-binaries.yaml with: - base_reth_node_version: 38de4e038 + base_reth_node_version: feature/load-test-benchmark load-test: name: Run load test benchmark diff --git a/clients/build-base-reth-node.sh b/clients/build-base-reth-node.sh index ab0bd852..f998f854 100755 --- a/clients/build-base-reth-node.sh +++ b/clients/build-base-reth-node.sh @@ -40,7 +40,8 @@ fi # Checkout specified version/commit echo "Checking out version: $BASE_RETH_NODE_VERSION" -git checkout -f "$BASE_RETH_NODE_VERSION" +git fetch origin "$BASE_RETH_NODE_VERSION" || true +git checkout -f "$BASE_RETH_NODE_VERSION" || git checkout -f "origin/$BASE_RETH_NODE_VERSION" # Build the binaries using cargo echo "Building base-reth-node, base-builder, and base-load-test with cargo..." From 2490bbcc713f94aeab8ac30c6bdb0ef17f4f9d55 Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 15:17:01 -0700 Subject: [PATCH 13/15] fix: use versions.env for base repo version Update versions.env to point at feature/load-test-benchmark and update the default in _build-binaries.yaml. Remove explicit version overrides from load-test.yaml and examples.yaml. --- .github/workflows/_build-binaries.yaml | 2 +- .github/workflows/examples.yaml | 1 - .github/workflows/load-test.yaml | 2 -- clients/versions.env | 2 +- 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/_build-binaries.yaml b/.github/workflows/_build-binaries.yaml index 0a9accc8..4824d6f8 100644 --- a/.github/workflows/_build-binaries.yaml +++ b/.github/workflows/_build-binaries.yaml @@ -19,7 +19,7 @@ on: description: "Base Reth Node version to build" required: false type: string - default: "main" + default: "feature/load-test-benchmark" # Set minimal permissions for all jobs by default permissions: diff --git a/.github/workflows/examples.yaml b/.github/workflows/examples.yaml index 1656537a..21823488 100644 --- a/.github/workflows/examples.yaml +++ b/.github/workflows/examples.yaml @@ -18,7 +18,6 @@ jobs: with: optimism_version: 3019251e80aa248e91743addd3e833190acb26f1 geth_version: 6cbfcd5161083bcd4052edc3022d9f99c6fe40e0 - base_reth_node_version: feature/load-test-benchmark example-benchmarks: runs-on: ubuntu-latest diff --git a/.github/workflows/load-test.yaml b/.github/workflows/load-test.yaml index 9edace1e..de9d06a7 100644 --- a/.github/workflows/load-test.yaml +++ b/.github/workflows/load-test.yaml @@ -12,8 +12,6 @@ jobs: build-binaries: name: Build binaries uses: ./.github/workflows/_build-binaries.yaml - with: - base_reth_node_version: feature/load-test-benchmark load-test: name: Run load test benchmark diff --git a/clients/versions.env b/clients/versions.env index 536ac9a8..3427491a 100644 --- a/clients/versions.env +++ b/clients/versions.env @@ -12,7 +12,7 @@ GETH_VERSION="v1.101604.0" # Base Reth Node Configuration BASE_RETH_NODE_REPO="https://github.com/base/base" -BASE_RETH_NODE_VERSION="main" +BASE_RETH_NODE_VERSION="feature/load-test-benchmark" # Build Configuration # BUILD_DIR="./build" From 1779c3fd89066b835eae75a5715c6c93834ba8d4 Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 15:25:34 -0700 Subject: [PATCH 14/15] fix: specify package for base-load-test binary target cargo can't find the bin target without -p base-load-tests because it's in a different workspace package than the default. --- clients/build-base-reth-node.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/build-base-reth-node.sh b/clients/build-base-reth-node.sh index f998f854..74fa7361 100755 --- a/clients/build-base-reth-node.sh +++ b/clients/build-base-reth-node.sh @@ -45,7 +45,7 @@ git checkout -f "$BASE_RETH_NODE_VERSION" || git checkout -f "origin/$BASE_RETH_ # Build the binaries using cargo echo "Building base-reth-node, base-builder, and base-load-test with cargo..." -cargo build --bin base-reth-node --bin base-builder --bin base-load-test --profile maxperf +cargo build --bin base-reth-node --bin base-builder -p base-load-tests --bin base-load-test --profile maxperf # Copy binaries to output directory echo "Copying binaries to output directory..." From 433962720e47f45dd610a15c24e0c8ad6445409d Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Fri, 27 Mar 2026 15:51:51 -0700 Subject: [PATCH 15/15] fix: split cargo build into two commands for separate packages --- clients/build-base-reth-node.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clients/build-base-reth-node.sh b/clients/build-base-reth-node.sh index 74fa7361..7341be5f 100755 --- a/clients/build-base-reth-node.sh +++ b/clients/build-base-reth-node.sh @@ -45,7 +45,8 @@ git checkout -f "$BASE_RETH_NODE_VERSION" || git checkout -f "origin/$BASE_RETH_ # Build the binaries using cargo echo "Building base-reth-node, base-builder, and base-load-test with cargo..." -cargo build --bin base-reth-node --bin base-builder -p base-load-tests --bin base-load-test --profile maxperf +cargo build --bin base-reth-node --bin base-builder --profile maxperf +cargo build -p base-load-tests --bin base-load-test --profile maxperf # Copy binaries to output directory echo "Copying binaries to output directory..."