Skip to content

rewrite of sei-load generator and sender.#56

Open
pompon0 wants to merge 41 commits into
mainfrom
gprusak-nonce-reset
Open

rewrite of sei-load generator and sender.#56
pompon0 wants to merge 41 commits into
mainfrom
gprusak-nonce-reset

Conversation

@pompon0

@pompon0 pompon0 commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Primary reason for the rewrite is support for non-happy paths for autobahn loadtesting - rejected transactions/not successfully executed/etc. The idea is that if sending a tx fails, we need to check the account nonce before sending the next transaction. Note that this affects only accounts from the long-lived pools - accounts generated for the sake of sending just 1 transaction (aka "new accounts") do not benefit from this extra logic.

The nonces, as well as the txs waiting to be sent are managed by TxsQueue, which ensures that:

  • inserted (generated) transactions have expected nonces
  • transactions per account are sent sequentially (otherwise they will be rejected by autobahn)

TxsQueue is managed by ShardedSender.

Additionally

  • removed unnecessary abstractions in both sender and generator logic
  • made Generator.Run accept the sender which exposes Nonce(), Flush() and Send() calls
  • added Generator <-> Sender integration tests
  • removed open/closed loop logic (might need to be reintroduced later if needed)
  • removed utils/rng in favor of just using a single Rand synchronously (we don't have other use cases). If concurrent Rand usage is needed, a SplitRng method was introduced (slower but robust alternative to SplitMix).

@pompon0
pompon0 requested a review from bdchatham June 26, 2026 16:14
@pompon0
pompon0 marked this pull request as ready for review June 29, 2026 16:59
@cursor

cursor Bot commented Jun 29, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Large architectural change to tx generation, signing, nonce handling, and removal of open-loop scheduling; incorrect nonce or flush logic could mis-load the chain or hide coordinated-omission behavior.

Overview
This PR rewrites the load-test generator and sender so autobahn-style failures can be handled without wedging long-lived accounts.

Sender path: Transactions stay unsigned until send; scenarios return unsigned txs and signing moves to the sender. ShardedSender (with per-account queuing) exposes Nonce, Send, and Flush so tracked pool accounts get sequential nonces, RPC nonce refresh, and queue reset after stale or rejected sends; one-shot “new” accounts skip that tracking. ethClient is simplified (multi-endpoint dial, address sharding) and the old per-worker request channels and QueuePool are removed.

Generator path: The Generator interface, weighted/scenario/prewarm helpers, and Dispatcher / open-loop scheduler are removed. Generator.Run(ctx, rng, txSender) drives the campaign in a loop; weighting is expanded instances plus shuffle. ResolveSeed returns a single math/rand/v2 PRNG; SetStream on distributions and gas pickers is gone—callers pass *rand.Rand into SampleIndex / GenerateGas.

Config & wiring: Settings.Validate now only enforces MaxInFlight > 0 (arrival-model checks removed). main spawns gen.Run instead of a dispatcher; prewarm is gen.Prewarm. funder.FundAccounts takes a flat address list. pkg/errors and utils/rng are dropped from go.mod usage in the diff.

Reviewed by Cursor Bugbot for commit 59dd2f4. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread sender/sharded_sender.go
Comment thread sender/txs_queue.go
Comment thread main.go
Comment thread sender/txs_queue.go
Comment thread sender/sharded_sender.go
}, nil
cfg: cfg,
queue: NewTxsQueue(cfg.Settings.MaxInFlight),
limiter: limiter,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Buffer size no longer bounds queue

Medium Severity

NewShardedSender sizes TxsQueue only from Settings.MaxInFlight. Settings.BufferSize and LoadConfig.TotalQueueSize() are no longer used, so existing configs that tune bufferSize/--buffer-size do not limit queue depth or memory as before.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 34ba3fe. Configure here.

Comment thread sender/metrics.go
attribute.String("chain_id", stats.ChainID),
))
}
}*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worker queue metric disabled

Low Severity

The worker_queue_length observable gauge callback no longer records observations: the ShardStats loop is commented out and only assigns _ = ss. Scrapers always see an empty series after the sender rewrite removed per-shard queues.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 34ba3fe. Configure here.

Comment thread generator/generator.go Outdated
Comment thread generator/generator.go
Comment thread generator/generator.go
Comment thread main.go
Comment thread main.go
// Start the sender (starts all workers)
s.SpawnBgNamed("sender", func() error { return sharedSender.Run(ctx) })
log.Printf("✅ Connected to %d endpoints", len(cfg.Endpoints))
snd = sharedSender

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Workers setting no longer applied

Medium Severity

The send path now runs a single ShardedSender background task and no longer uses Settings.TasksPerEndpoint (workers) or LoadConfig.GetNumShards, even though those settings remain in config, CLI, and tests. Raising --workers does not increase RPC parallelism as documented.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit a28e7c0. Configure here.

Comment thread generator/generator.go
instance.Deployed = true

if address.Cmp(common.Address{}) != 0 {
address := instance.Scenario.Deploy(g.config, deployer, uint64(i))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy nonces skip unused slots

High Severity

Sequential scenario deployment passes the scenario list index as the deployer nonce. Instances that do not broadcast a deployment transaction still advance that index, so the next contract deployment can be signed with a nonce above the account’s on-chain nonce and be rejected.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit cce23ae. Configure here.

Comment thread sender/sharded_sender.go
Comment thread sender/writer.go
if err != nil {
return fmt.Errorf("tx.EthTx.MarshalBinary(): %w", err)
}
txData.TxPayloads = append(txData.TxPayloads, payload)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TxsWriter emits unsigned payloads

High Severity

Transaction signing moved into ShardedSender, so generators now hand off unsigned txs. The TxsDir path uses TxsWriter, which marshals EthTx directly without signing. Written tx_payloads are therefore not valid raw transactions for later submission.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 10fe1d9. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

There are 6 total unresolved issues (including 5 from previous reviews).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 59dd2f4. Configure here.

Comment thread main.go
if err := funder.FundAccounts(ctx, cfg, addrs); err != nil {
return fmt.Errorf("failed to fund accounts: %w", err)
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Funding skipped for txs-dir path

Medium Severity

Account funding now runs only in the ShardedSender branch. When TxsDir is set, FundAccounts is never called even if cfg.Funding is configured, so written txs can target unfunded accounts when replayed.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 59dd2f4. Configure here.

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.

2 participants