Use new `engine_newPayloadV3`
This commit is contained in:
parent
f7352d18cf
commit
058137327a
2
setup.py
2
setup.py
|
@ -578,7 +578,7 @@ def get_pow_chain_head() -> PowBlock:
|
|||
|
||||
class NoopExecutionEngine(ExecutionEngine):
|
||||
|
||||
def notify_new_payload(self: ExecutionEngine, execution_payload: ExecutionPayload) -> bool:
|
||||
def notify_new_payload(self: ExecutionEngine, new_payload_request: NewPayloadRequest) -> bool:
|
||||
return True
|
||||
|
||||
def notify_forkchoice_updated(self: ExecutionEngine,
|
||||
|
|
|
@ -178,12 +178,11 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
|||
process_block_header(state, block)
|
||||
if is_execution_enabled(state, block.body):
|
||||
process_withdrawals(state, block.body.execution_payload)
|
||||
process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE) # [Modified in EIP6110]
|
||||
process_execution_payload(state, block.body, EXECUTION_ENGINE) # [Modified in EIP6110]
|
||||
process_randao(state, block.body)
|
||||
process_eth1_data(state, block.body)
|
||||
process_operations(state, block.body) # [Modified in EIP6110]
|
||||
process_sync_aggregate(state, block.body.sync_aggregate)
|
||||
process_blob_kzg_commitments(block.body)
|
||||
```
|
||||
|
||||
#### Modified `process_operations`
|
||||
|
@ -238,7 +237,9 @@ def process_deposit_receipt(state: BeaconState, deposit_receipt: DepositReceipt)
|
|||
*Note*: The function `process_execution_payload` is modified to use the new `ExecutionPayloadHeader` type.
|
||||
|
||||
```python
|
||||
def process_execution_payload(state: BeaconState, payload: ExecutionPayload, execution_engine: ExecutionEngine) -> None:
|
||||
def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None:
|
||||
payload = body.execution_payload
|
||||
|
||||
# Verify consistency of the parent hash with respect to the previous execution payload header
|
||||
if is_merge_transition_complete(state):
|
||||
assert payload.parent_hash == state.latest_execution_payload_header.block_hash
|
||||
|
@ -247,7 +248,8 @@ def process_execution_payload(state: BeaconState, payload: ExecutionPayload, exe
|
|||
# Verify timestamp
|
||||
assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
|
||||
# Verify the execution payload is valid
|
||||
assert execution_engine.notify_new_payload(payload)
|
||||
versioned_hashes = [kzg_commitment_to_versioned_hash(commitment) for commitment in body.blob_kzg_commitments]
|
||||
assert execution_engine.notify_new_payload(NewPayloadRequest(execution_payload=payload))
|
||||
# Cache execution payload header
|
||||
state.latest_execution_payload_header = ExecutionPayloadHeader(
|
||||
parent_hash=payload.parent_hash,
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
- [Modified `slash_validator`](#modified-slash_validator)
|
||||
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
|
||||
- [Execution engine](#execution-engine)
|
||||
- [Request data](#request-data)
|
||||
- [`NewPayloadRequest`](#newpayloadrequest)
|
||||
- [Engine APIs](#engine-apis)
|
||||
- [`notify_new_payload`](#notify_new_payload)
|
||||
- [Block processing](#block-processing)
|
||||
- [Execution payload](#execution-payload)
|
||||
|
@ -300,6 +303,18 @@ def slash_validator(state: BeaconState,
|
|||
|
||||
### Execution engine
|
||||
|
||||
#### Request data
|
||||
|
||||
##### `NewPayloadRequest`
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class NewPayloadRequest(object):
|
||||
execution_payload: ExecutionPayload
|
||||
```
|
||||
|
||||
#### Engine APIs
|
||||
|
||||
The implementation-dependent `ExecutionEngine` protocol encapsulates the execution sub-system logic via:
|
||||
|
||||
* a state object `self.execution_state` of type `ExecutionState`
|
||||
|
@ -313,7 +328,7 @@ The Engine API may be used to implement this and similarly defined functions via
|
|||
#### `notify_new_payload`
|
||||
|
||||
```python
|
||||
def notify_new_payload(self: ExecutionEngine, execution_payload: ExecutionPayload) -> bool:
|
||||
def notify_new_payload(self: ExecutionEngine, new_payload_request: NewPayloadRequest) -> bool:
|
||||
"""
|
||||
Return ``True`` if and only if ``execution_payload`` is valid with respect to ``self.execution_state``.
|
||||
"""
|
||||
|
@ -328,7 +343,7 @@ def notify_new_payload(self: ExecutionEngine, execution_payload: ExecutionPayloa
|
|||
def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
||||
process_block_header(state, block)
|
||||
if is_execution_enabled(state, block.body):
|
||||
process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE) # [New in Bellatrix]
|
||||
process_execution_payload(state, block.body, EXECUTION_ENGINE) # [New in Bellatrix]
|
||||
process_randao(state, block.body)
|
||||
process_eth1_data(state, block.body)
|
||||
process_operations(state, block.body)
|
||||
|
@ -340,7 +355,9 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
|||
##### `process_execution_payload`
|
||||
|
||||
```python
|
||||
def process_execution_payload(state: BeaconState, payload: ExecutionPayload, execution_engine: ExecutionEngine) -> None:
|
||||
def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None:
|
||||
payload = body.execution_payload
|
||||
|
||||
# Verify consistency of the parent hash with respect to the previous execution payload header
|
||||
if is_merge_transition_complete(state):
|
||||
assert payload.parent_hash == state.latest_execution_payload_header.block_hash
|
||||
|
@ -349,7 +366,7 @@ def process_execution_payload(state: BeaconState, payload: ExecutionPayload, exe
|
|||
# Verify timestamp
|
||||
assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
|
||||
# Verify the execution payload is valid
|
||||
assert execution_engine.notify_new_payload(payload)
|
||||
assert execution_engine.notify_new_payload(NewPayloadRequest(execution_payload=payload))
|
||||
# Cache execution payload header
|
||||
state.latest_execution_payload_header = ExecutionPayloadHeader(
|
||||
parent_hash=payload.parent_hash,
|
||||
|
|
|
@ -333,7 +333,7 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
|||
process_block_header(state, block)
|
||||
if is_execution_enabled(state, block.body):
|
||||
process_withdrawals(state, block.body.execution_payload) # [New in Capella]
|
||||
process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE) # [Modified in Capella]
|
||||
process_execution_payload(state, block.body, EXECUTION_ENGINE) # [Modified in Capella]
|
||||
process_randao(state, block.body)
|
||||
process_eth1_data(state, block.body)
|
||||
process_operations(state, block.body) # [Modified in Capella]
|
||||
|
@ -407,7 +407,9 @@ def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None:
|
|||
*Note*: The function `process_execution_payload` is modified to use the new `ExecutionPayloadHeader` type.
|
||||
|
||||
```python
|
||||
def process_execution_payload(state: BeaconState, payload: ExecutionPayload, execution_engine: ExecutionEngine) -> None:
|
||||
def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None:
|
||||
payload = body.execution_payload
|
||||
|
||||
# Verify consistency of the parent hash with respect to the previous execution payload header
|
||||
if is_merge_transition_complete(state):
|
||||
assert payload.parent_hash == state.latest_execution_payload_header.block_hash
|
||||
|
@ -416,7 +418,7 @@ def process_execution_payload(state: BeaconState, payload: ExecutionPayload, exe
|
|||
# Verify timestamp
|
||||
assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
|
||||
# Verify the execution payload is valid
|
||||
assert execution_engine.notify_new_payload(payload)
|
||||
assert execution_engine.notify_new_payload(NewPayloadRequest(execution_payload=payload))
|
||||
# Cache execution payload header
|
||||
state.latest_execution_payload_header = ExecutionPayloadHeader(
|
||||
parent_hash=payload.parent_hash,
|
||||
|
|
|
@ -24,13 +24,15 @@
|
|||
- [Helper functions](#helper-functions)
|
||||
- [Misc](#misc)
|
||||
- [`kzg_commitment_to_versioned_hash`](#kzg_commitment_to_versioned_hash)
|
||||
- [`tx_peek_blob_versioned_hashes`](#tx_peek_blob_versioned_hashes)
|
||||
- [`verify_kzg_commitments_against_transactions`](#verify_kzg_commitments_against_transactions)
|
||||
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
|
||||
- [Execution engine](#execution-engine)
|
||||
- [Request data](#request-data)
|
||||
- [Modified `NewPayloadRequest`](#modified-newpayloadrequest)
|
||||
- [Engine APIs](#engine-apis)
|
||||
- [Modified `notify_new_payload`](#modified-notify_new_payload)
|
||||
- [Block processing](#block-processing)
|
||||
- [Execution payload](#execution-payload)
|
||||
- [`process_execution_payload`](#process_execution_payload)
|
||||
- [Blob KZG commitments](#blob-kzg-commitments)
|
||||
- [Testing](#testing)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
@ -158,43 +160,33 @@ def kzg_commitment_to_versioned_hash(kzg_commitment: KZGCommitment) -> Versioned
|
|||
return VERSIONED_HASH_VERSION_KZG + hash(kzg_commitment)[1:]
|
||||
```
|
||||
|
||||
#### `tx_peek_blob_versioned_hashes`
|
||||
|
||||
This function retrieves the hashes from the `SignedBlobTransaction` as defined in Deneb, using SSZ offsets.
|
||||
Offsets are little-endian `uint32` values, as defined in the [SSZ specification](../../ssz/simple-serialize.md).
|
||||
See [the full details of `blob_versioned_hashes` offset calculation](https://gist.github.com/protolambda/23bd106b66f6d4bb854ce46044aa3ca3).
|
||||
|
||||
```python
|
||||
def tx_peek_blob_versioned_hashes(opaque_tx: Transaction) -> Sequence[VersionedHash]:
|
||||
assert opaque_tx[0] == BLOB_TX_TYPE
|
||||
message_offset = 1 + uint32.decode_bytes(opaque_tx[1:5])
|
||||
# field offset: 32 + 8 + 32 + 32 + 8 + 4 + 32 + 4 + 4 + 32 = 188
|
||||
blob_versioned_hashes_offset = (
|
||||
message_offset
|
||||
+ uint32.decode_bytes(opaque_tx[(message_offset + 188):(message_offset + 192)])
|
||||
)
|
||||
# `VersionedHash` is a 32-byte object
|
||||
assert (len(opaque_tx) - blob_versioned_hashes_offset) % 32 == 0
|
||||
return [
|
||||
VersionedHash(opaque_tx[x:(x + 32)])
|
||||
for x in range(blob_versioned_hashes_offset, len(opaque_tx), 32)
|
||||
]
|
||||
```
|
||||
|
||||
#### `verify_kzg_commitments_against_transactions`
|
||||
|
||||
```python
|
||||
def verify_kzg_commitments_against_transactions(transactions: Sequence[Transaction],
|
||||
kzg_commitments: Sequence[KZGCommitment]) -> bool:
|
||||
all_versioned_hashes: List[VersionedHash] = []
|
||||
for tx in transactions:
|
||||
if tx[0] == BLOB_TX_TYPE:
|
||||
all_versioned_hashes += tx_peek_blob_versioned_hashes(tx)
|
||||
return all_versioned_hashes == [kzg_commitment_to_versioned_hash(commitment) for commitment in kzg_commitments]
|
||||
```
|
||||
|
||||
## Beacon chain state transition function
|
||||
|
||||
### Execution engine
|
||||
|
||||
#### Request data
|
||||
|
||||
##### Modified `NewPayloadRequest`
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class NewPayloadRequest(object):
|
||||
execution_payload: ExecutionPayload
|
||||
versioned_hashes: Sequence[VersionedHash]
|
||||
```
|
||||
|
||||
#### Engine APIs
|
||||
|
||||
#### Modified `notify_new_payload`
|
||||
|
||||
```python
|
||||
def notify_new_payload(self: ExecutionEngine, new_payload_request: NewPayloadRequest) -> bool:
|
||||
"""
|
||||
Return ``True`` if and only if ``execution_payload`` is valid with respect to ``self.execution_state``.
|
||||
"""
|
||||
...
|
||||
```
|
||||
|
||||
### Block processing
|
||||
|
||||
```python
|
||||
|
@ -202,12 +194,11 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
|||
process_block_header(state, block)
|
||||
if is_execution_enabled(state, block.body):
|
||||
process_withdrawals(state, block.body.execution_payload)
|
||||
process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE) # [Modified in Deneb]
|
||||
process_execution_payload(state, block.body, EXECUTION_ENGINE) # [Modified in Deneb]
|
||||
process_randao(state, block.body)
|
||||
process_eth1_data(state, block.body)
|
||||
process_operations(state, block.body)
|
||||
process_sync_aggregate(state, block.body.sync_aggregate)
|
||||
process_blob_kzg_commitments(block.body) # [New in Deneb]
|
||||
```
|
||||
|
||||
#### Execution payload
|
||||
|
@ -215,7 +206,9 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
|||
##### `process_execution_payload`
|
||||
|
||||
```python
|
||||
def process_execution_payload(state: BeaconState, payload: ExecutionPayload, execution_engine: ExecutionEngine) -> None:
|
||||
def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None:
|
||||
payload = body.execution_payload
|
||||
|
||||
# Verify consistency of the parent hash with respect to the previous execution payload header
|
||||
if is_merge_transition_complete(state):
|
||||
assert payload.parent_hash == state.latest_execution_payload_header.block_hash
|
||||
|
@ -224,7 +217,8 @@ def process_execution_payload(state: BeaconState, payload: ExecutionPayload, exe
|
|||
# Verify timestamp
|
||||
assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
|
||||
# Verify the execution payload is valid
|
||||
assert execution_engine.notify_new_payload(payload)
|
||||
versioned_hashes = [kzg_commitment_to_versioned_hash(commitment) for commitment in body.blob_kzg_commitments]
|
||||
assert execution_engine.notify_new_payload(NewPayloadRequest(execution_payload=payload, versioned_hashes=versioned_hashes))
|
||||
|
||||
# Cache execution payload header
|
||||
state.latest_execution_payload_header = ExecutionPayloadHeader(
|
||||
|
@ -247,13 +241,6 @@ def process_execution_payload(state: BeaconState, payload: ExecutionPayload, exe
|
|||
)
|
||||
```
|
||||
|
||||
#### Blob KZG commitments
|
||||
|
||||
```python
|
||||
def process_blob_kzg_commitments(body: BeaconBlockBody) -> None:
|
||||
assert verify_kzg_commitments_against_transactions(body.execution_payload.transactions, body.blob_kzg_commitments)
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
*Note*: The function `initialize_beacon_state_from_eth1` is modified for pure Deneb testing only.
|
||||
|
|
|
@ -98,8 +98,8 @@ def validate_blobs_and_kzg_commitments(execution_payload: ExecutionPayload,
|
|||
blobs: Sequence[Blob],
|
||||
blob_kzg_commitments: Sequence[KZGCommitment],
|
||||
blob_kzg_proofs: Sequence[KZGProof]) -> None:
|
||||
# Optionally sanity-check that the KZG commitments match the versioned hashes in the transactions
|
||||
assert verify_kzg_commitments_against_transactions(execution_payload.transactions, blob_kzg_commitments)
|
||||
# TODO: can we just remove it?
|
||||
# assert verify_kzg_commitments_against_transactions(execution_payload.transactions, blob_kzg_commitments)
|
||||
|
||||
# Optionally sanity-check that the KZG commitments match the blobs (as produced by the execution engine)
|
||||
assert len(blob_kzg_commitments) == len(blobs) == len(blob_kzg_proofs)
|
||||
|
|
|
@ -29,10 +29,10 @@ def run_execution_payload_processing(spec, state, execution_payload, valid=True,
|
|||
called_new_block = False
|
||||
|
||||
class TestEngine(spec.NoopExecutionEngine):
|
||||
def notify_new_payload(self, payload) -> bool:
|
||||
def notify_new_payload(self, new_payload_request) -> bool:
|
||||
nonlocal called_new_block, execution_valid
|
||||
called_new_block = True
|
||||
assert payload == execution_payload
|
||||
assert new_payload_request.execution_payload == execution_payload
|
||||
return execution_valid
|
||||
|
||||
if not valid:
|
||||
|
|
|
@ -143,7 +143,7 @@ def process_and_sign_block_without_header_validations(spec, state, block):
|
|||
)
|
||||
if is_post_bellatrix(spec):
|
||||
if spec.is_execution_enabled(state, block.body):
|
||||
spec.process_execution_payload(state, block.body.execution_payload, spec.EXECUTION_ENGINE)
|
||||
spec.process_execution_payload(state, block.body, spec.EXECUTION_ENGINE)
|
||||
|
||||
# Perform rest of process_block transitions
|
||||
spec.process_randao(state, block.body)
|
||||
|
|
Loading…
Reference in New Issue