Merge pull request #2479 from mkalinin/randao_in_execution_payload
Add randao to execution payload
This commit is contained in:
commit
00afb341de
2
setup.py
2
setup.py
|
@ -532,7 +532,7 @@ class NoopExecutionEngine(ExecutionEngine):
|
||||||
def finalize_block(self, block_hash: Hash32) -> bool:
|
def finalize_block(self, block_hash: Hash32) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def assemble_block(self, block_hash: Hash32, timestamp: uint64) -> ExecutionPayload:
|
def assemble_block(self, block_hash: Hash32, timestamp: uint64, random: Bytes32) -> ExecutionPayload:
|
||||||
raise NotImplementedError("no default block production")
|
raise NotImplementedError("no default block production")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -92,8 +92,9 @@ class ExecutionPayload(Container):
|
||||||
parent_hash: Hash32
|
parent_hash: Hash32
|
||||||
coinbase: Bytes20 # 'beneficiary' in the yellow paper
|
coinbase: Bytes20 # 'beneficiary' in the yellow paper
|
||||||
state_root: Bytes32
|
state_root: Bytes32
|
||||||
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
|
|
||||||
receipt_root: Bytes32 # 'receipts root' in the yellow paper
|
receipt_root: Bytes32 # 'receipts root' in the yellow paper
|
||||||
|
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
|
||||||
|
random: Bytes32 # 'difficulty' in the yellow paper
|
||||||
block_number: uint64 # 'number' in the yellow paper
|
block_number: uint64 # 'number' in the yellow paper
|
||||||
gas_limit: uint64
|
gas_limit: uint64
|
||||||
gas_used: uint64
|
gas_used: uint64
|
||||||
|
@ -111,8 +112,9 @@ class ExecutionPayloadHeader(Container):
|
||||||
parent_hash: Hash32
|
parent_hash: Hash32
|
||||||
coinbase: Bytes20
|
coinbase: Bytes20
|
||||||
state_root: Bytes32
|
state_root: Bytes32
|
||||||
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
|
|
||||||
receipt_root: Bytes32
|
receipt_root: Bytes32
|
||||||
|
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
|
||||||
|
random: Bytes32
|
||||||
block_number: uint64
|
block_number: uint64
|
||||||
gas_limit: uint64
|
gas_limit: uint64
|
||||||
gas_used: uint64
|
gas_used: uint64
|
||||||
|
@ -196,12 +198,15 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
||||||
|
|
||||||
#### `process_execution_payload`
|
#### `process_execution_payload`
|
||||||
|
|
||||||
|
*Note:* This function depends on `process_randao` function call as it retrieves the most recent randao mix from the `state`. Implementations that are considering parallel processing of execution payload with respect to beacon chain state transition function should work around this dependency.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def process_execution_payload(state: BeaconState, payload: ExecutionPayload, execution_engine: ExecutionEngine) -> None:
|
def process_execution_payload(state: BeaconState, payload: ExecutionPayload, execution_engine: ExecutionEngine) -> None:
|
||||||
# Verify consistency of the parent hash and block number
|
# Verify consistency of the parent hash, block number and random
|
||||||
if is_merge_complete(state):
|
if is_merge_complete(state):
|
||||||
assert payload.parent_hash == state.latest_execution_payload_header.block_hash
|
assert payload.parent_hash == state.latest_execution_payload_header.block_hash
|
||||||
assert payload.block_number == state.latest_execution_payload_header.block_number + uint64(1)
|
assert payload.block_number == state.latest_execution_payload_header.block_number + uint64(1)
|
||||||
|
assert payload.random == get_randao_mix(state, get_current_epoch(state))
|
||||||
# Verify timestamp
|
# Verify timestamp
|
||||||
assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
|
assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
|
||||||
# Verify the execution payload is valid
|
# Verify the execution payload is valid
|
||||||
|
@ -211,8 +216,9 @@ def process_execution_payload(state: BeaconState, payload: ExecutionPayload, exe
|
||||||
parent_hash=payload.parent_hash,
|
parent_hash=payload.parent_hash,
|
||||||
coinbase=payload.coinbase,
|
coinbase=payload.coinbase,
|
||||||
state_root=payload.state_root,
|
state_root=payload.state_root,
|
||||||
logs_bloom=payload.logs_bloom,
|
|
||||||
receipt_root=payload.receipt_root,
|
receipt_root=payload.receipt_root,
|
||||||
|
logs_bloom=payload.logs_bloom,
|
||||||
|
random=payload.random,
|
||||||
block_number=payload.block_number,
|
block_number=payload.block_number,
|
||||||
gas_limit=payload.gas_limit,
|
gas_limit=payload.gas_limit,
|
||||||
gas_used=payload.gas_used,
|
gas_used=payload.gas_used,
|
||||||
|
@ -266,6 +272,7 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Bytes32,
|
||||||
# [New in Merge] Initialize the execution payload header (with block number set to 0)
|
# [New in Merge] Initialize the execution payload header (with block number set to 0)
|
||||||
state.latest_execution_payload_header.block_hash = eth1_block_hash
|
state.latest_execution_payload_header.block_hash = eth1_block_hash
|
||||||
state.latest_execution_payload_header.timestamp = eth1_timestamp
|
state.latest_execution_payload_header.timestamp = eth1_timestamp
|
||||||
|
state.latest_execution_payload_header.random = eth1_block_hash
|
||||||
|
|
||||||
return state
|
return state
|
||||||
```
|
```
|
||||||
|
|
|
@ -49,7 +49,7 @@ The body of this function is implementation dependent.
|
||||||
The Consensus API may be used to implement this with an external execution engine.
|
The Consensus API may be used to implement this with an external execution engine.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def assemble_block(self: ExecutionEngine, block_hash: Hash32, timestamp: uint64) -> ExecutionPayload:
|
def assemble_block(self: ExecutionEngine, block_hash: Hash32, timestamp: uint64, random: Bytes32) -> ExecutionPayload:
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -70,8 +70,23 @@ Let `get_pow_chain_head() -> PowBlock` be the function that returns the head of
|
||||||
* Set `block.body.execution_payload = get_execution_payload(state, transition_store, execution_engine)` where:
|
* Set `block.body.execution_payload = get_execution_payload(state, transition_store, execution_engine)` where:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
def compute_randao_mix(state: BeaconState, randao_reveal: BLSSignature) -> Bytes32:
|
||||||
|
epoch = get_current_epoch(state)
|
||||||
|
return xor(get_randao_mix(state, epoch), hash(randao_reveal))
|
||||||
|
|
||||||
|
|
||||||
|
def produce_execution_payload(state: BeaconState,
|
||||||
|
parent_hash: Hash32,
|
||||||
|
randao_reveal: BLSSignature,
|
||||||
|
execution_engine: ExecutionEngine) -> ExecutionPayload:
|
||||||
|
timestamp = compute_timestamp_at_slot(state, state.slot)
|
||||||
|
randao_mix = compute_randao_mix(state, randao_reveal)
|
||||||
|
return execution_engine.assemble_block(parent_hash, timestamp, randao_mix)
|
||||||
|
|
||||||
|
|
||||||
def get_execution_payload(state: BeaconState,
|
def get_execution_payload(state: BeaconState,
|
||||||
transition_store: TransitionStore,
|
transition_store: TransitionStore,
|
||||||
|
randao_reveal: BLSSignature,
|
||||||
execution_engine: ExecutionEngine) -> ExecutionPayload:
|
execution_engine: ExecutionEngine) -> ExecutionPayload:
|
||||||
if not is_merge_complete(state):
|
if not is_merge_complete(state):
|
||||||
pow_block = get_pow_chain_head()
|
pow_block = get_pow_chain_head()
|
||||||
|
@ -80,11 +95,9 @@ def get_execution_payload(state: BeaconState,
|
||||||
return ExecutionPayload()
|
return ExecutionPayload()
|
||||||
else:
|
else:
|
||||||
# Signify merge via producing on top of the last PoW block
|
# Signify merge via producing on top of the last PoW block
|
||||||
timestamp = compute_time_at_slot(state, state.slot)
|
return produce_execution_payload(state, pow_block.block_hash, randao_reveal, execution_engine)
|
||||||
return execution_engine.assemble_block(pow_block.block_hash, timestamp)
|
|
||||||
|
|
||||||
# Post-merge, normal payload
|
# Post-merge, normal payload
|
||||||
execution_parent_hash = state.latest_execution_payload_header.block_hash
|
parent_hash = state.latest_execution_payload_header.block_hash
|
||||||
timestamp = compute_time_at_slot(state, state.slot)
|
return produce_execution_payload(state, parent_hash, randao_reveal, execution_engine)
|
||||||
return execution_engine.assemble_block(execution_parent_hash, timestamp)
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -93,13 +93,15 @@ def build_empty_block(spec, state, slot=None):
|
||||||
empty_block.body.eth1_data.deposit_count = state.eth1_deposit_index
|
empty_block.body.eth1_data.deposit_count = state.eth1_deposit_index
|
||||||
empty_block.parent_root = parent_block_root
|
empty_block.parent_root = parent_block_root
|
||||||
|
|
||||||
|
apply_randao_reveal(spec, state, empty_block)
|
||||||
|
|
||||||
if is_post_altair(spec):
|
if is_post_altair(spec):
|
||||||
empty_block.body.sync_aggregate.sync_committee_signature = spec.G2_POINT_AT_INFINITY
|
empty_block.body.sync_aggregate.sync_committee_signature = spec.G2_POINT_AT_INFINITY
|
||||||
|
|
||||||
if is_post_merge(spec):
|
if is_post_merge(spec):
|
||||||
empty_block.body.execution_payload = build_empty_execution_payload(spec, state)
|
randao_mix = spec.compute_randao_mix(state, empty_block.body.randao_reveal)
|
||||||
|
empty_block.body.execution_payload = build_empty_execution_payload(spec, state, randao_mix)
|
||||||
|
|
||||||
apply_randao_reveal(spec, state, empty_block)
|
|
||||||
return empty_block
|
return empty_block
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
def build_empty_execution_payload(spec, state):
|
def build_empty_execution_payload(spec, state, randao_mix=None):
|
||||||
"""
|
"""
|
||||||
Assuming a pre-state of the same slot, build a valid ExecutionPayload without any transactions.
|
Assuming a pre-state of the same slot, build a valid ExecutionPayload without any transactions.
|
||||||
"""
|
"""
|
||||||
|
@ -6,13 +6,17 @@ def build_empty_execution_payload(spec, state):
|
||||||
timestamp = spec.compute_time_at_slot(state, state.slot)
|
timestamp = spec.compute_time_at_slot(state, state.slot)
|
||||||
empty_txs = spec.List[spec.Transaction, spec.MAX_TRANSACTIONS_PER_PAYLOAD]()
|
empty_txs = spec.List[spec.Transaction, spec.MAX_TRANSACTIONS_PER_PAYLOAD]()
|
||||||
|
|
||||||
|
if randao_mix is None:
|
||||||
|
randao_mix = spec.get_randao_mix(state, spec.get_current_epoch(state))
|
||||||
|
|
||||||
payload = spec.ExecutionPayload(
|
payload = spec.ExecutionPayload(
|
||||||
parent_hash=latest.block_hash,
|
parent_hash=latest.block_hash,
|
||||||
coinbase=spec.Bytes20(),
|
coinbase=spec.Bytes20(),
|
||||||
state_root=latest.state_root, # no changes to the state
|
state_root=latest.state_root, # no changes to the state
|
||||||
logs_bloom=spec.ByteVector[spec.BYTES_PER_LOGS_BLOOM](), # TODO: zeroed logs bloom for empty logs ok?
|
|
||||||
receipt_root=b"no receipts here" + b"\x00" * 16, # TODO: root of empty MPT may be better.
|
receipt_root=b"no receipts here" + b"\x00" * 16, # TODO: root of empty MPT may be better.
|
||||||
|
logs_bloom=spec.ByteVector[spec.BYTES_PER_LOGS_BLOOM](), # TODO: zeroed logs bloom for empty logs ok?
|
||||||
block_number=latest.block_number + 1,
|
block_number=latest.block_number + 1,
|
||||||
|
random=randao_mix,
|
||||||
gas_limit=latest.gas_limit, # retain same limit
|
gas_limit=latest.gas_limit, # retain same limit
|
||||||
gas_used=0, # empty block, 0 gas
|
gas_used=0, # empty block, 0 gas
|
||||||
timestamp=timestamp,
|
timestamp=timestamp,
|
||||||
|
@ -30,8 +34,9 @@ def get_execution_payload_header(spec, execution_payload):
|
||||||
parent_hash=execution_payload.parent_hash,
|
parent_hash=execution_payload.parent_hash,
|
||||||
coinbase=execution_payload.coinbase,
|
coinbase=execution_payload.coinbase,
|
||||||
state_root=execution_payload.state_root,
|
state_root=execution_payload.state_root,
|
||||||
logs_bloom=execution_payload.logs_bloom,
|
|
||||||
receipt_root=execution_payload.receipt_root,
|
receipt_root=execution_payload.receipt_root,
|
||||||
|
logs_bloom=execution_payload.logs_bloom,
|
||||||
|
random=execution_payload.random,
|
||||||
block_number=execution_payload.block_number,
|
block_number=execution_payload.block_number,
|
||||||
gas_limit=execution_payload.gas_limit,
|
gas_limit=execution_payload.gas_limit,
|
||||||
gas_used=execution_payload.gas_used,
|
gas_used=execution_payload.gas_used,
|
||||||
|
|
Loading…
Reference in New Issue