What's wrong
The merge builder rejects nearly every forwarded block late in each slot with
LimitExceeded("max orders per slot"), and merging stops for that slot.
The two sides count the same budget differently. The relay counts distinct
orders (Conn::orders_sent, crates/relay/src/block_merging/tile.rs:67). The
builder counts announcements: state.orders_admitted += 1 runs for every order
in every block (crates/builder/src/engine/mod.rs:543), before the dedup on
the next line. Builders resubmit near-identical blocks all slot, so the builder
hits its own advertised cap (8192) while the relay thinks it is far below it.
The check also runs before state.blocks.insert, so a rejected block never
registers and the "same block re-forwarded" shortcut at mod.rs:508 never
applies. Every re-forward makes a new reject.
Repro
relay-mainnet-1-aws-fr, slot 15127548, hundreds of lines in under a second:
WARN block_merging::tile: merging reject slot=15127548 code=LimitExceeded subject=BlockHash(0x8a671385...) msg=limit exceeded: max orders per slot
Failing test: repeat_announcements_do_not_consume_the_order_budget.
Steps (each becomes one PR)
Open questions
The relay keys an order on its hash; the builder keys on
keccak(order_hash || builder_pubkey), since attribution is per-builder. One
public tx carried by N builders is 1 against the relay's budget and N against
the builder's. Bounded by builder count, not resubmission rate, so much smaller
than the above. Measure after step 1 before deciding if it needs a step.
What's wrong
The merge builder rejects nearly every forwarded block late in each slot with
LimitExceeded("max orders per slot"), and merging stops for that slot.The two sides count the same budget differently. The relay counts distinct
orders (
Conn::orders_sent,crates/relay/src/block_merging/tile.rs:67). Thebuilder counts announcements:
state.orders_admitted += 1runs for every orderin every block (
crates/builder/src/engine/mod.rs:543), before the dedup onthe next line. Builders resubmit near-identical blocks all slot, so the builder
hits its own advertised cap (8192) while the relay thinks it is far below it.
The check also runs before
state.blocks.insert, so a rejected block neverregisters and the "same block re-forwarded" shortcut at
mod.rs:508neverapplies. Every re-forward makes a new reject.
Repro
relay-mainnet-1-aws-fr, slot 15127548, hundreds of lines in under a second:Failing test:
repeat_announcements_do_not_consume_the_order_budget.Steps (each becomes one PR)
(tests:
repeat_announcements_do_not_consume_the_order_budget,distinct_orders_still_hit_the_per_slot_cap) (PR: )Open questions
The relay keys an order on its hash; the builder keys on
keccak(order_hash || builder_pubkey), since attribution is per-builder. Onepublic tx carried by N builders is 1 against the relay's budget and N against
the builder's. Bounded by builder count, not resubmission rate, so much smaller
than the above. Measure after step 1 before deciding if it needs a step.