Skip to content

Commit 7d3ab43

Browse files
committed
Add block building function overview
1 parent 4415640 commit 7d3ab43

File tree

2 files changed

+140
-13
lines changed

2 files changed

+140
-13
lines changed

docs/flashblocks.md

Lines changed: 140 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,140 @@
1-
## Flashblock flow details
2-
This is sequence diagram for flashblock building flow, rollup-boost, op-node and fallback sequencer interaction.
1+
# Flashblock flow details
2+
FCU w/ attr - engine_forkchoiceUpdated with payloadAttributes. This starts block building.
3+
FCU w/o attr - engine_forkchoiceUpdated without payloadAttributes. This progresses the unsafe/safe/finalized head.
4+
newPayload - engine_newPayload. This provides the execution client with new canonical block.
5+
getPayload - engine_getPayload. Collects block building results. In flashblocks, this is only used to terminate block building
6+
as flashblocks are assembled on rollup-boost side.
37

4-
There is 2 separate cases, for regular block and for block with no-txpool flag. When building no-txpool block we are using only fallback EL to construct the block.
5-
This is done to rely on canonical implementation for such block as they are not compute intensive.
6-
## Regular block building flow
7-
```mermaid
8+
## build_payload Function Overview
9+
This is the function that produces the block and contains all logic responsible for building the block and producing flashblocks
10+
```pseudocode
11+
function build_payload(build_arguments, best_payload_cell):
12+
// 1. Set up the state for block building
13+
apply_pre_execution_changes()
14+
// === FALLBACK BLOCK CREATION ===
15+
// Produces deposits only block
16+
execute_sequencer_transactions()
17+
// 2. Add builder transaction if we build block with txpool enabled (specified in FCU)
18+
if transaction_pool_enabled:
19+
add_builder_tx_after_deposits()
20+
21+
// 3. Build and publish initial fallback block
22+
fallback_payload = build_block(state, context, execution_info)
23+
best_payload_cell.set(fallback_payload)
24+
// 4. Store the block in trie cache. This cache would be looked up on the next FCU w/ attr
25+
send_payload_to_engine(fallback_payload)
26+
// 5. Send fb via websocket
27+
publish_flashblock(fallback_payload)
28+
29+
// 6. Return early if transaction pool is disabled
30+
if no_transaction_pool:
31+
record_metrics_and_return()
32+
33+
// === FLASHBLOCKS TIMING CALCULATION ===
34+
// 7. Calculate dynamic flashblock timing and number of flashblocks we are able to produce based on the formula
35+
// first_offset = (block timestamp - current timestamp) % flashblock_time
36+
// flashblocks_count = (block timestamp - current timestamp) // flashblock_time
37+
// Ex: If we started building flashblocks at 400ms (because of network latency) that means we have only
38+
// 600ms to build the block (assuming block time is 1s)
39+
// If we have 250ms flashblock time, we could build only 3 flashblocks, the first one must be sent after 100ms and others
40+
// after 250ms each.
41+
(flashblocks_count, first_offset) = calculate_flashblocks_timing(timestamp)
42+
43+
// 8. Calculate resource limits per flashblock
44+
gas_per_flashblock = total_gas_limit / flashblocks_count
45+
da_per_flashblock = total_da_limit / flashblocks_count
46+
47+
// === FLASHBLOCKS BUILDING LOOP ===
48+
49+
// 9. Setup timing coordination. This timer task produces a cancel token that would be cancelled when it's time to
50+
// send the flashblock.
51+
setup_timer_task(first_offset, flashblock_interval)
52+
// 10. We use a custom wrapper around reth BestTransaction iterator. Our wrapper tracks committed transactions and skips
53+
// them when we build a new flashblock.
54+
create_best_transactions_iterator()
55+
56+
// 10. Main flashblock building loop
57+
loop:
58+
// Wait for next flashblock timing signal
59+
flashblock_cancel_token = wait_for_next_flashblock_signal()
60+
61+
if flashblock_cancel_token is None:
62+
break // All flashblocks completed or parent cancelled
63+
64+
if reached_target_flashblock_count():
65+
continue // Skip if we've built enough flashblocks
66+
67+
// === SINGLE FLASHBLOCK BUILDING ===
68+
69+
// 11. Provide a fresh BestTransaction iterator that would contain all transactions in mempool that could be
70+
// included in the flashblock
71+
refresh_transaction_iterator_for_current_flashblock()
72+
73+
// 12. Execute transactions within limits
74+
execute_best_transactions():
75+
while has_transactions() and within_limits():
76+
transaction = get_next_best_transaction()
77+
if can_execute(transaction, gas_limit, da_limit):
78+
execute_transaction(transaction)
79+
update_cumulative_usage()
80+
else:
81+
skip_transaction()
82+
// If we cannot fit a transaction, we will remove this tx and its ancestors from this round of
83+
// flashblock building
84+
mark_invalid()
85+
86+
// 13. Add builder transaction to last flashblock
87+
if is_last_flashblock():
88+
add_builder_tx_to_block()
89+
90+
// 14. Build block and create flashblock payload
91+
(new_payload, flashblock_payload) = build_block(state, context, info)
92+
93+
// 15. Wait for timing coordination
94+
wait_for_flashblock_timing_completion()
95+
96+
if parent_build_cancelled():
97+
break // If the main cancel token is cancelled we must start a new block building job and all previous
98+
// results are obsolete.
99+
100+
// 16. Publish flashblock and update state
101+
publish_flashblock(flashblock_payload)
102+
best_payload_cell.set(new_payload)
103+
send_payload_to_engine(new_payload)
104+
105+
// 17. Update limits for next flashblock
106+
increment_flashblock_index()
107+
increase_gas_and_da_limits_for_next_flashblock()
108+
mark_committed_transactions()
109+
110+
// === CLEANUP PHASE ===
111+
112+
// 18. Record final metrics and cleanup
113+
record_flashblocks_metrics()
114+
return success
115+
```
116+
117+
### Timing Coordination
118+
- **Timer Task**: Spawned async task that sends timing signals at regular intervals
119+
- **First Offset**: Timeout after which we must send the flashblock. We calculate it so we send flashblocks at `current time % flashblock_time == 0`
120+
- **Cancellation Tokens**: When we cancel the flashblock token we stop this flashblock building process and publish it.
121+
122+
### Caveats
123+
If the system clock drifts too much we will print an error message and fallback to producing flashblocks with regular flashblock_time intervals, without adjusting anything.
124+
125+
## Block building flow
126+
These are sequence diagrams for flashblock building flow, rollup-boost, op-node and fallback sequencer interaction.
127+
128+
There are 2 separate cases: for regular blocks and for blocks with the no-txpool flag. When building no-txpool blocks we are using only the fallback EL to construct the block.
129+
This is done to rely on the canonical implementation for such blocks as they are not compute intensive.
8130

131+
### Regular block building flow
132+
![regular block building flow](regular_block_flow.png)
133+
### No txpool block building flow
134+
![no txpool block building flow](no_txpool_block_flow.png)
135+
136+
### Raw sequence diagrams
137+
```
9138
participant op-rbuilder
10139
participant op-geth
11140
participant rollup-boost
@@ -18,7 +147,7 @@ rollup-boost -> op-geth: FCU w/ attr
18147
rollup-boost -> op-rbuilder: FCU w/ attr
19148
op-geth -> rollup-boost: VALID/SYNCING
20149
op-rbuilder -> rollup-boost: VALID/SYNCING
21-
rollup-boost -> rollup-boost: Set that op-rbuilder is building this block
150+
rollup-boost -> rollup-boost: Mark that op-rbuilder is building this block
22151
rollup-boost -> op-node: op-geth VALID/SYNCING
23152
op-rbuilder -> op-rbuilder: Start block building
24153
op-geth -> op-geth: Build regular block
@@ -33,14 +162,14 @@ op-node -> rollup-boost: getPayload
33162
group There is in-mem flashblock
34163
rollup-boost -> rollup-boost: Build payload from locally stored FBs
35164
rollup-boost -> op-node: Payload from local FBs
36-
rollup-boost --> op-rbuilder: getPayload to stop building, without waiting for an answer
165+
rollup-boost --> op-rbuilder: getPayload to stop building, without waiting for a response
37166
end
38-
group There is no in-mem flashblocks, by builder marked as building payload
167+
group There is no in-mem flashblocks, but builder is marked as building payload
39168
rollup-boost -> op-geth: getPayload
40169
rollup-boost -> op-rbuilder: getPayload
41170
rollup-boost -> op-node: op-rbuilder payload, if present, op-geth otherwise. Selection policy may be used if present
42171
end
43-
group There is no in-mem flashblocks, by builder is not marked as building payload
172+
group There is no in-mem flashblocks, but builder is not marked as building payload
44173
rollup-boost -> op-geth: getPayload
45174
rollup-boost -> op-node: op-geth payload
46175
end
@@ -55,9 +184,7 @@ rollup-boost -> op-rbuilder: newPayload
55184
end
56185
```
57186

58-
## Basic no-txpool flow
59-
```mermaid
60-
187+
```
61188
participant op-rbuilder
62189
participant op-geth
63190
participant rollup-boost

docs/regular_block_flow.png

240 KB
Loading

0 commit comments

Comments
 (0)