Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update EIP-4844: Refactor Validity Conditions #6583

Merged
merged 10 commits into from
May 29, 2023
82 changes: 52 additions & 30 deletions EIPS/eip-4844.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,7 @@ rlp([
The value of `excess_data_gas` can be calculated using the parent header and number of blobs in the block.

```python
def calc_excess_data_gas(parent: Header, new_blobs: int) -> int:
consumed_data_gas = new_blobs * DATA_GAS_PER_BLOB
def calc_excess_data_gas(parent: Header, consumed_data_gas: int) -> int:
if parent.excess_data_gas + consumed_data_gas < TARGET_DATA_GAS_PER_BLOCK:
return 0
else:
Expand All @@ -163,22 +162,6 @@ def calc_excess_data_gas(parent: Header, new_blobs: int) -> int:

For the first post-fork block, `parent.excess_data_gas` is evaluated as `0`.

### Beacon chain validation

On the consensus-layer the blobs are now referenced, but not fully encoded, in the beacon block body.
Instead of embedding the full contents in the body, the blobs are propagated separately, as a "sidecar".

This "sidecar" design provides forward compatibility for further data increases by black-boxing `is_data_available()`:
with full sharding `is_data_available()` can be replaced by data-availability-sampling (DAS) thus avoiding all blobs being downloaded by all beacon nodes on the network.

Note that the consensus-layer is tasked with persisting the blobs for data availability, the execution-layer is not.

The `ethereum/consensus-specs` repository defines the following beacon-node changes involved in this EIP:

- Beacon chain: process updated beacon blocks and ensure blobs are available.
- P2P network: gossip and sync updated beacon block types and new blobs sidecars.
- Honest validator: produce beacon blocks with blobs, publish the blobs sidecars.

### Opcode to get versioned hashes

We add an instruction `BLOBHASH` (with opcode `HASH_OPCODE_BYTE`) which reads `index` from the top of the stack
Expand Down Expand Up @@ -239,30 +222,69 @@ def get_data_gasprice(header: Header) -> int:
)
```

The block validity conditions are modified to include data gas checks:
The block validity conditions are modified to include data gas checks (see the [Execution layer validation](#execution-layer-validation) section below).

The actual `data_fee` as calculated via `calc_data_fee` is deducted from the sender balance before transaction execution and burned, and is not refunded in case of transaction failure.

### Consensus layer validation

On the consensus layer the blobs are referenced, but not fully encoded, in the beacon block body.
Instead of embedding the full contents in the body, the blobs are propagated separately, as "sidecars".

This "sidecar" design provides forward compatibility for further data increases by black-boxing `is_data_available()`:
with full sharding `is_data_available()` can be replaced by data-availability-sampling (DAS) thus avoiding all blobs being downloaded by all beacon nodes on the network.

Note that the consensus layer is tasked with persisting the blobs for data availability, the execution layer is not.

The `ethereum/consensus-specs` repository defines the following consensus layer changes involved in this EIP:

- Beacon chain: process updated beacon blocks and ensure blobs are available.
- P2P network: gossip and sync updated beacon block types and new blob sidecars.
- Honest validator: produce beacon blocks with blobs; sign and publish the associated blob sidecars.

### Execution layer validation

On the execution layer, the block validity conditions are extended as follows:

```python
def validate_block(block: Block) -> None:
...

num_blobs = 0
block_data_gas = 0

for tx in block.transactions:
lightclient marked this conversation as resolved.
Show resolved Hide resolved
...

# the signer must be able to afford the transaction
assert signer(tx).balance >= tx.gas * tx.max_fee_per_gas + get_total_data_gas(tx) * tx.max_fee_per_data_gas
# modify the check for sufficient balance
max_total_fee = tx.gas * tx.max_fee_per_gas
if type(tx) is SignedBlobTransaction:
max_total_fee += get_total_data_gas(tx) * tx.max_fee_per_data_gas
assert signer(tx).balance >= max_total_fee

# ensure that the user was willing to at least pay the current data gasprice
assert tx.max_fee_per_data_gas >= get_data_gasprice(parent(block).header)
...

num_blobs += len(tx.blob_versioned_hashes)
# add validity logic specific to blob txs
if type(tx) is SignedBlobTransaction:

# check that the excess data gas is correct
expected_edg = calc_excess_data_gas(parent(block).header, num_blobs)
assert expected_edg == block.excess_data_gas
```
# there must be at least one blob
assert len(tx.message.blob_versioned_hashes) > 0

The actual `data_fee` as calculated via `calc_data_fee` is deducted from the sender balance before transaction execution and burned, and is not refunded in case of transaction failure.
# all versioned blob hashes must start with BLOB_COMMITMENT_VERSION_KZG
for blob_versioned_hash in tx.message.blob_versioned_hashes:
assert blob_versioned_hash[0] == BLOB_COMMITMENT_VERSION_KZG

# ensure that the user was willing to at least pay the current data gasprice
assert tx.max_fee_per_data_gas >= get_data_gasprice(parent(block).header)

# keep track of total data gas spent in the block
block_data_gas += get_total_data_gas(tx)

# ensure the total data gas spent is at most equal to the limit
assert block_data_gas <= MAX_DATA_GAS_PER_BLOCK

# check that the excess data gas was updated correctly
assert block.header.excess_data_gas == calc_excess_data_gas(parent(block).header, block_data_gas)
```

### Networking

Expand Down