Skip to content

Commit

Permalink
Update the blocks processing sequence
Browse files Browse the repository at this point in the history
  • Loading branch information
Arkenan committed May 27, 2024
1 parent b81b679 commit b51eec1
Showing 1 changed file with 42 additions and 33 deletions.
75 changes: 42 additions & 33 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,52 +211,61 @@ The most relevant piece of the spec here is the [get_weight](https://eth2book.in

### Receiving a block

A block is first received and sent to the `PendingBlocks` GenServer, which checks if the block has everything needed or if it's duplicated before letting it be processed.

```mermaid
sequenceDiagram
participant prod as Topic Producer (GenStage)
participant proc as Topic Processor (Broadway)
participant block as Block DB
participant state as Beacon States DB
participant port as Libp2pPort
participant block as BeaconBlock
participant pending as PendingBlocks
activate block
port ->> block: {:gossipsub, {topic, id, message}}
block ->> block: Decompress and deserialize message
block ->> port: validate_message(id, :accept)
block ->> pending: {:add_block, SignedBeaconBlock}
deactivate block
```

However, the block isn't processed immediately. Once every 500ms, `PendingBlocks` checks if there are blocks that should be processed and does so.

```mermaid
sequenceDiagram
participant pending as PendingBlocks
participant FC as Fork-choice store
participant exec as Execution Client
prod ->> proc: Produce demand
proc ->> proc: Decompress and deserialize message
proc ->>+ proc: on_block(block)
proc ->> exec: Validate execution payload
exec -->> proc: ok
proc ->> FC: request validation metadata
FC -->> proc: return
proc ->> proc: Validate block
proc ->> block: Save new block
proc ->> proc: Calculate state transition
proc ->> state: Save new beacon state metadata
proc ->> FC: Add a new block to the tree and update weights
loop
proc ->>- proc: process_operations
end
participant rec as recompute_head <br> (async task)
participant StoreDB
participant subs as OperationsCollector <br> Validators <br> ExecutionClient <br> BeaconChain
pending ->> pending: :process_blocks
activate pending
loop
proc ->> proc: on_attestation
pending ->> pending: check which blocks are pending <br> check parent is downloaded and processed
pending ->>+ FC: {:on_block, block_root, signed_block, from}
deactivate pending
end
```
Receiving a block is more complex:
FC ->> FC: process_block
FC ->>+ rec: recompute_head(store)
FC ->> FC: prune_old_states
FC ->> pending: {:block_processed, block_root, true}
deactivate FC
rec ->> StoreDB: pruned_store
rec ->> rec: Handlers.get_head()
rec ->> subs: notify_new_block
- The block itself needs to be stored.
- The state transition needs to be applied, a new beacon state calculated, and stored separately.
- A new node needs to be added to the block tree aside from updating weights.
- on_attestation needs to be called for each attestation.
```

For the happy path, shown above, fork choice store calculates the state transition, and notifies the pending blocks GenServer that the block was correctly processed, so it can mark it as such.

Also, there's a more complex case: we can only include a block in the fork tree if we know of its parents and their connection with our current finalized checkpoint. If we receive a disconnected node, we'll need to use Request-Response to ask peers for the missing blocks.
Asynchronously, a new task is started to recompute the new head, as this takes a significant amount of time. When the head is recomputed, multiple processes are notified.

## Request-Response

**TO DO**: document how ports work for this.

### Pending blocks

**TO DO**: document pending blocks design.

### Checkpoint sync

**TO DO**: document checkpoint sync.
Expand Down

0 comments on commit b51eec1

Please sign in to comment.