owned this note
owned this note
Published
Linked with GitHub
# Nimbus-Eth2 ExecutionPayloadHeader.blog_gas_used
## Short description
Nimbus-Eth2 always sets ExecutionPayloadHeader.blob_gas_used to 0 in LightClient headers and is thus not spec complient (Deneb).
## Attack scenario
This happens when requesting LightClient data for Deneb blocks (e.g. on the devchain12) via the Beacon API (and likely via the p2p /eth2/beacon_chain/req/light_client* request/response interface), if that block contains a blob (and thus uses blob gas).
It might also happen when another node requests LightClient data via the p2p wire protocol.
## Impact
Light Clients will receive bad data from the node (according to the consensus-specs they check validity of this value when checking the validity of the light clients headers) and thus stop accepting updates until this is resolved. While this likely won't impact the block production, it can have an impact on various applications relying on the light client sync, likely including layer-2 networks and bridges, which might become unavailable when receiving a block that uses any blob gas.
If other nodes request LightClient data from a Nimbus-Eth2 node and get bad data, they might drop it out of its peer list, thus segregating Nimbus-Eth2 clients from the rest of the network.
Nimbus-Eth2 nodes themselves will be impacted by this because they (by default) use the light client protocol for faster synchronization with the network. They might either stop syncing and require different settings or they might sync slower.
As far as I can tell these values are also persisted, thus if this isn't noticed early enough it might require re-syncing the node or repair the persisted state through other means, to be able to provide valid light client updates again. Combined with the potential network segregation this could have a significant impact due to (potentially) all Nimbus-Eth2 nodes getting removed from the peer lists of nodes requesting light client data and not being able to restart/reconnect immediately.
## Components
https://github.com/status-im/nimbus-eth2/blob/stable/beacon_chain/spec/forks_light_client.nim Line 933: toDenebLightClientHeader(denebBlock) does not copy the blob_gas_used field and instead sets it to a default value of 0
## Reproduction
Setup a Nimbus-Eth2 client (tested with version v24.1.1-0e63f8-stateofus) on devchain12 (or another chain that is on Deneb and makes use of blobs, but then you have to adjust the slot numbers). Note that the node might not have the data for the slots below available.
Then execute the following Rest API calls against it (shown with curl + jq; the lines after the curl command show the annotated, truncated output):
```bash
# Get first LightClientUpdate on Deneb (as JSON)
curl 'http://localhost:5052/eth/v1/beacon/light_client/updates?start_period=1&count=1' -v|jq '.[0].data.attested_header.execution'
{
# ...
"block_number": "8151",
"block_hash": "0x88110c5ad95e2d03a382d578b5b0f515fbece9e2aa780d4e9ec84cc2684108e4",
"blob_gas_used": "0", # Wrong value
"excess_blob_gas": "47316992"
}
# Get the same data via beacon/blocks (as JSON)
curl http://localhost:5052/eth/v2/beacon/blocks/8258|jq '.data.message.body.execution_payload | del(.transactions)'
{
# ...
"block_number": "8151",
"block_hash": "0x88110c5ad95e2d03a382d578b5b0f515fbece9e2aa780d4e9ec84cc2684108e4",
"blob_gas_used": "131072", # Correct value
"excess_blob_gas": "47316992"
}
# Alternative: Get first LightClientUpdate on Deneb (as SSZ)
curl 'http://localhost:5052/eth/v1/beacon/light_client/updates?start_period=1&count=1' -H 'accept: application/octet-stream' | xxd -p|tr -d '\n'|grep -oP '88110c5ad95e2d03a382d578b5b0f515fbece9e2aa780d4e9ec84cc2684108e4.*' | grep --color -P '88110c5ad95e2d03a382d578b5b0f515fbece9e2aa780d4e9ec84cc2684108e4|\d{16}(?=0000d20200000000)'
# 88110c5ad95e2d03a382d578b5b0f515fbece9e2aa780d4e9ec84cc2684108e4 # Blockhash
# 35f785b33a35c6db7ca10365365d4f715d581efb12b2d0ec54c988c63b29d7a9 # Txn Root
# 792930bbd5baac43bcc798ee49aa8185ef76bb3b44ba62b91d86ae569e4bb535 # Withdrawals Root
# 0000000000000000 # Wrong value
# 0000d20200000000 # excess_blob_gas
# Get the same data via beacon/blocks (as SSZ)
curl http://localhost:5052/eth/v2/beacon/blocks/8258 -H 'accept: application/octet-stream' | xxd -p|tr -d '\n'|grep -oP '88110c5ad95e2d03a382d578b5b0f515fbece9e2aa780d4e9ec84cc2684108e4.*' | grep --color -P '88110c5ad95e2d03a382d578b5b0f515fbece9e2aa780d4e9ec84cc2684108e4|\d{16}(?=0000d20200000000)'
# 88110c5ad95e2d03a382d578b5b0f515fbece9e2aa780d4e9ec84cc2684108e4 # Blockhash
# 1a0200003b040000 # Other data
# 0000020000000000 # Correct value
# 0000d20200000000 # excess_blob_gas
# Alternative: Via Bootstrap endpoint (as JSON)
curl "http://localhost:5052/eth/v1/beacon/light_client/bootstrap/$(curl -X GET "http://localhost:5052/eth/v1/beacon/headers/$((251*32))" 2>/dev/null |jq .data.root | tr -d '"')" -v 2>/dev/null |jq .data.header.execution
{
# ...
"block_number": "7925",
"block_hash": "0x45aa3339c954f336457342838562d2fff2548284ca1da1164f9db9e973619c6a",
"blob_gas_used": "0", # Wrong value
"excess_blob_gas": "76677120"
}
# Get the same data via beacon/blocks (as JSON)
curl http://localhost:5052/eth/v2/beacon/blocks/$((251*32)) 2>/dev/null |jq '.data.message.body.execution_payload | del(.transactions)'
{
# ...
"block_number": "7925",
"block_hash": "0x45aa3339c954f336457342838562d2fff2548284ca1da1164f9db9e973619c6a",
"blob_gas_used": "131072", # Correct value
"excess_blob_gas": "76677120"
}
```
The same values can be obtained using the beacon API in the webbrowser, I've used curl + jq for better reproducibility.
## Fix
Add the following line to https://github.com/status-im/nimbus-eth2/blob/stable/beacon_chain/spec/forks_light_client.nim (line 949):
```nim
blob_gas_used: payload.blob_gas_used,
```
## Details
Nimbus-Eth2 does have some tests for the light client, but I don't think they have run with Deneb types, yet. Even then: They would likely be running without the use of blob transactions, thus this bug would likely not be shown with the existing tests.