Reth payload builder
When the consensus layer asks for a block (engine_forkchoiceUpdated with payload attributes), Reth starts a payload job. The basic job calls your builder again and again, keeping the best result, until the payload is resolved, its deadline passes, or an attempt returns Freeze, so building is a loop of attempts, not a single call.
A custom chain changes what goes into a block (ordering, system transactions, a different fee rule) by implementing the PayloadBuilder trait from reth_basic_payload_builder and plugging it into the node's components.
API at a glance
fn try_build(&self, args: BuildArguments<Attrs, Payload>) -> Result<BuildOutcome<Payload>, PayloadBuilderError>- One attempt at a better payload. Called repeatedly by the job.
BuildOutcome::{Better, Aborted, Cancelled, Freeze}- Better: a new best payload. Aborted: the attempt paid less in fees than the current best. Cancelled: the job was cancelled. Freeze: the payload is final; stop building.
fn build_empty_payload(&self, config: PayloadConfig<…>) -> Result<Payload, PayloadBuilderError>- A block with no transactions, used when the payload is resolved and no built payload is ready; by default it races any attempt still in progress.
fn on_missing_payload(&self, args) -> MissingPayloadBehaviour<Payload>- What to do when the payload is resolved and none is ready. The default races an empty payload (RaceEmptyPayload).
BuildArguments { cached_reads, config, cancel, best_payload, … }- What each attempt gets: cached state reads from earlier attempts, the payload config (parent header and attributes), a cancel token and the best payload so far.
BasicPayloadJobGenerator / PayloadBuilderService- The generator starts a job per payload request around your builder; the service receives the engine's requests and hands them to the generator.
Checked against paradigmxyz/reth at eb4c15e (2026-04-07): crates/payload/basic/src/lib.rs, crates/payload/builder/src/service.rs
Lessons on this topic
Custom PayloadBuilder = sequencer-mode block production. Reth-as-sequencer (centralised L2) needs this. Read the customisation pattern.
op-rbuilder is the Rust sequencer that powers OP-Reth nodes — written by Flashbots, built on Reth SDK. Read the actual block-building loop, see exactly…
Build a payment rail you'd run for Stripe or Meta. Concretely — in chainspec, executor, precompiles, indexer — what's different from an L1 you'd run for…