mirror of
https://github.com/status-im/eth2.0-specs.git
synced 2025-02-23 07:48:12 +00:00
Merge branch 'hardcoded-ttd' into tests/merge
This commit is contained in:
commit
8bfa5188c1
2
Makefile
2
Makefile
@ -173,7 +173,7 @@ define run_generator
|
||||
echo "generator $(1) finished"
|
||||
endef
|
||||
|
||||
# The tests dir itself is simply build by creating the directory (recursively creating deeper directories if necessary)
|
||||
# The tests dir itself is simply built by creating the directory (recursively creating deeper directories if necessary)
|
||||
$(TEST_VECTOR_DIR):
|
||||
$(info creating test output directory, for generators: ${GENERATOR_TARGETS})
|
||||
mkdir -p $@
|
||||
|
@ -45,7 +45,7 @@ The merge is still actively in development. The exact specification has not been
|
||||
* [Merge fork](specs/merge/fork.md)
|
||||
* [Fork Choice changes](specs/merge/fork-choice.md)
|
||||
* [Validator additions](specs/merge/validator.md)
|
||||
* [Client settings](specs/merge/client_settings.md)
|
||||
* [Client settings](specs/merge/client-settings.md)
|
||||
|
||||
### Sharding
|
||||
|
||||
|
@ -3,6 +3,12 @@
|
||||
# Extends the mainnet preset
|
||||
PRESET_BASE: 'mainnet'
|
||||
|
||||
# Transition
|
||||
# ---------------------------------------------------------------
|
||||
# TBD, 2**256-1 is a placeholder
|
||||
TERMINAL_TOTAL_DIFFICULTY: 115792089237316195423570985008687907853269984665640564039457584007913129639935
|
||||
|
||||
|
||||
# Genesis
|
||||
# ---------------------------------------------------------------
|
||||
# `2**14` (= 16,384)
|
||||
@ -31,9 +37,6 @@ MERGE_FORK_EPOCH: 18446744073709551615
|
||||
SHARDING_FORK_VERSION: 0x03000000
|
||||
SHARDING_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
# TBD, 2**32 is a placeholder. Merge transition approach is in active R&D.
|
||||
MIN_ANCHOR_POW_BLOCK_DIFFICULTY: 4294967296
|
||||
|
||||
|
||||
# Time parameters
|
||||
# ---------------------------------------------------------------
|
||||
|
@ -3,6 +3,12 @@
|
||||
# Extends the minimal preset
|
||||
PRESET_BASE: 'minimal'
|
||||
|
||||
# Transition
|
||||
# ---------------------------------------------------------------
|
||||
# TBD, 2**256-1 is a placeholder
|
||||
TERMINAL_TOTAL_DIFFICULTY: 115792089237316195423570985008687907853269984665640564039457584007913129639935
|
||||
|
||||
|
||||
# Genesis
|
||||
# ---------------------------------------------------------------
|
||||
# [customized]
|
||||
@ -30,9 +36,6 @@ MERGE_FORK_EPOCH: 18446744073709551615
|
||||
SHARDING_FORK_VERSION: 0x03000001
|
||||
SHARDING_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
# TBD, 2**32 is a placeholder. Merge transition approach is in active R&D.
|
||||
MIN_ANCHOR_POW_BLOCK_DIFFICULTY: 4294967296
|
||||
|
||||
|
||||
# Time parameters
|
||||
# ---------------------------------------------------------------
|
||||
|
3
setup.py
3
setup.py
@ -509,8 +509,7 @@ ExecutionState = Any
|
||||
|
||||
|
||||
def get_pow_block(hash: Bytes32) -> PowBlock:
|
||||
return PowBlock(block_hash=hash, parent_hash=Bytes32(), is_valid=True, is_processed=True,
|
||||
total_difficulty=uint256(0), difficulty=uint256(0))
|
||||
return PowBlock(block_hash=hash, parent_hash=Bytes32(), total_difficulty=uint256(0), difficulty=uint256(0))
|
||||
|
||||
|
||||
def get_execution_state(execution_state_root: Bytes32) -> ExecutionState:
|
||||
|
@ -14,6 +14,7 @@
|
||||
- [Execution](#execution)
|
||||
- [Configuration](#configuration)
|
||||
- [Genesis testing settings](#genesis-testing-settings)
|
||||
- [Transition settings](#transition-settings)
|
||||
- [Containers](#containers)
|
||||
- [Extended containers](#extended-containers)
|
||||
- [`BeaconBlockBody`](#beaconblockbody)
|
||||
@ -64,6 +65,7 @@ This patch adds transaction execution to the beacon chain as part of the Merge f
|
||||
| `BYTES_PER_LOGS_BLOOM` | `uint64(2**8)` (= 256) |
|
||||
| `GAS_LIMIT_DENOMINATOR` | `uint64(2**10)` (= 1,024) |
|
||||
| `MIN_GAS_LIMIT` | `uint64(5000)` (= 5,000) |
|
||||
| `MAX_EXTRA_DATA_BYTES` | `2**5` (= 32) |
|
||||
|
||||
## Configuration
|
||||
|
||||
@ -76,6 +78,12 @@ This patch adds transaction execution to the beacon chain as part of the Merge f
|
||||
| `GENESIS_GAS_LIMIT` | `uint64(30000000)` (= 30,000,000) |
|
||||
| `GENESIS_BASE_FEE_PER_GAS` | `Bytes32('0x00ca9a3b00000000000000000000000000000000000000000000000000000000')` (= 1,000,000,000) |
|
||||
|
||||
### Transition settings
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `TERMINAL_TOTAL_DIFFICULTY` | **TBD** |
|
||||
|
||||
## Containers
|
||||
|
||||
### Extended containers
|
||||
@ -159,6 +167,7 @@ class ExecutionPayload(Container):
|
||||
gas_limit: uint64
|
||||
gas_used: uint64
|
||||
timestamp: uint64
|
||||
extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
|
||||
base_fee_per_gas: Bytes32 # base fee introduced in EIP-1559, little-endian serialized
|
||||
# Extra payload fields
|
||||
block_hash: Hash32 # Hash of execution block
|
||||
@ -180,6 +189,7 @@ class ExecutionPayloadHeader(Container):
|
||||
gas_limit: uint64
|
||||
gas_used: uint64
|
||||
timestamp: uint64
|
||||
extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
|
||||
base_fee_per_gas: Bytes32
|
||||
# Extra payload fields
|
||||
block_hash: Hash32 # Hash of execution block
|
||||
@ -246,15 +256,17 @@ The above function is accessed through the `EXECUTION_ENGINE` module which insta
|
||||
|
||||
### Block processing
|
||||
|
||||
*Note*: The call to the `process_execution_payload` must happen before the call to the `process_randao` as the former depends on the `randao_mix` computed with the reveal of the previous block.
|
||||
|
||||
```python
|
||||
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 Merge]
|
||||
process_randao(state, block.body)
|
||||
process_eth1_data(state, block.body)
|
||||
process_operations(state, block.body)
|
||||
process_sync_aggregate(state, block.body.sync_aggregate)
|
||||
if is_execution_enabled(state, block.body):
|
||||
process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE) # [New in Merge]
|
||||
```
|
||||
|
||||
### Execution payload processing
|
||||
@ -284,16 +296,16 @@ def is_valid_gas_limit(payload: ExecutionPayload, parent: ExecutionPayloadHeader
|
||||
|
||||
#### `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
|
||||
def process_execution_payload(state: BeaconState, payload: ExecutionPayload, execution_engine: ExecutionEngine) -> None:
|
||||
# Verify consistency of the parent hash, block number, random, base fee per gas and gas limit
|
||||
# Verify consistency of the parent hash, block number, base fee per gas and gas limit
|
||||
# with respect to the previous execution payload header
|
||||
if is_merge_complete(state):
|
||||
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.random == get_randao_mix(state, get_current_epoch(state))
|
||||
assert is_valid_gas_limit(payload, state.latest_execution_payload_header)
|
||||
# Verify random
|
||||
assert payload.random == get_randao_mix(state, get_current_epoch(state))
|
||||
# Verify timestamp
|
||||
assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
|
||||
# Verify the execution payload is valid
|
||||
@ -310,6 +322,7 @@ def process_execution_payload(state: BeaconState, payload: ExecutionPayload, exe
|
||||
gas_limit=payload.gas_limit,
|
||||
gas_used=payload.gas_used,
|
||||
timestamp=payload.timestamp,
|
||||
extra_data=payload.extra_data,
|
||||
base_fee_per_gas=payload.base_fee_per_gas,
|
||||
block_hash=payload.block_hash,
|
||||
transactions_root=hash_tree_root(payload.transactions),
|
||||
|
21
specs/merge/client-settings.md
Normal file
21
specs/merge/client-settings.md
Normal file
@ -0,0 +1,21 @@
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
||||
|
||||
- [The Merge -- Client Settings](#the-merge----client-settings)
|
||||
- [Override terminal total difficulty](#override-terminal-total-difficulty)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
# The Merge -- Client Settings
|
||||
|
||||
**Notice**: This document is a work-in-progress for researchers and implementers.
|
||||
|
||||
This document specifies configurable settings that clients must implement for the Merge.
|
||||
|
||||
### Override terminal total difficulty
|
||||
|
||||
To coordinate manual overrides to [`TERMINAL_TOTAL_DIFFICULTY`](./beacon-chain.md#Transition-settings) parameter, clients must provide `--terminal-total-difficulty-override` as a configurable setting. The value provided by this setting must take precedence over pre-configured `TERMINAL_TOTAL_DIFFICULTY` parameter.
|
||||
|
||||
Except under exceptional scenarios, this setting is expected to not be used. Sufficient warning to the user about this exceptional configurable setting should be provided.
|
||||
|
@ -1,26 +0,0 @@
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
||||
|
||||
- [The Merge -- Client Settings](#the-merge----client-settings)
|
||||
- [Override terminal total difficulty](#override-terminal-total-difficulty)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
# The Merge -- Client Settings
|
||||
|
||||
**Notice**: This document is a work-in-progress for researchers and implementers.
|
||||
|
||||
This document specifies configurable settings that clients must implement for the Merge.
|
||||
|
||||
### Override terminal total difficulty
|
||||
|
||||
To coordinate manual overrides to [`terminal_total_difficulty`](fork-choice.md#transitionstore), clients
|
||||
must provide `--terminal-total-difficulty-override` as a configurable setting.
|
||||
|
||||
If `TransitionStore` has already [been initialized](./fork.md#initializing-transition-store), this alters the previously initialized value of
|
||||
`TransitionStore.terminal_total_difficulty`, otherwise this setting initializes `TransitionStore` with the specified, bypassing `compute_terminal_total_difficulty` and the use of an `anchor_pow_block`.
|
||||
`terminal_total_difficulty`.
|
||||
|
||||
Except under exceptional scenarios, this setting is expected to not be used, and `terminal_total_difficulty` will operate with [default functionality](./fork.md#initializing-transition-store). Sufficient warning to the user about this exceptional configurable setting should be provided.
|
||||
[here](fork.md#initializing-transition-store).
|
@ -13,11 +13,9 @@
|
||||
- [`set_head`](#set_head)
|
||||
- [`finalize_block`](#finalize_block)
|
||||
- [Helpers](#helpers)
|
||||
- [`TransitionStore`](#transitionstore)
|
||||
- [`PowBlock`](#powblock)
|
||||
- [`get_pow_block`](#get_pow_block)
|
||||
- [`is_valid_terminal_pow_block`](#is_valid_terminal_pow_block)
|
||||
- [`process_merge_execution_payload`](#process_merge_execution_payload)
|
||||
- [Updated fork-choice handlers](#updated-fork-choice-handlers)
|
||||
- [`on_block`](#on_block)
|
||||
|
||||
@ -69,14 +67,6 @@ def finalize_block(self: ExecutionEngine, block_hash: Hash32) -> bool:
|
||||
|
||||
## Helpers
|
||||
|
||||
### `TransitionStore`
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class TransitionStore(object):
|
||||
terminal_total_difficulty: uint256
|
||||
```
|
||||
|
||||
### `PowBlock`
|
||||
|
||||
```python
|
||||
@ -84,8 +74,6 @@ class TransitionStore(object):
|
||||
class PowBlock(object):
|
||||
block_hash: Hash32
|
||||
parent_hash: Hash32
|
||||
is_processed: boolean
|
||||
is_valid: boolean
|
||||
total_difficulty: uint256
|
||||
difficulty: uint256
|
||||
```
|
||||
@ -94,30 +82,17 @@ class PowBlock(object):
|
||||
|
||||
Let `get_pow_block(block_hash: Hash32) -> PowBlock` be the function that given the hash of the PoW block returns its data.
|
||||
|
||||
*Note*: The `eth_getBlockByHash` JSON-RPC method does not distinguish invalid blocks from blocks that haven't been processed yet. Either extending this existing method or implementing a new one is required.
|
||||
*Note*: The `eth_getBlockByHash` JSON-RPC method may be used to pull this information from an execution client.
|
||||
|
||||
### `is_valid_terminal_pow_block`
|
||||
|
||||
Used by fork-choice handler, `on_block`.
|
||||
|
||||
```python
|
||||
def is_valid_terminal_pow_block(transition_store: TransitionStore, block: PowBlock, parent: PowBlock) -> bool:
|
||||
is_total_difficulty_reached = block.total_difficulty >= transition_store.terminal_total_difficulty
|
||||
is_parent_total_difficulty_valid = parent.total_difficulty < transition_store.terminal_total_difficulty
|
||||
return block.is_valid and is_total_difficulty_reached and is_parent_total_difficulty_valid
|
||||
```
|
||||
|
||||
### `process_merge_execution_payload`
|
||||
|
||||
Used by fork-choice handler, `on_block` to check validity of terminal block.
|
||||
|
||||
```python
|
||||
def process_merge_execution_payload(transition_store: TransitionStore, execution_payload: ExecutionPayload) -> None:
|
||||
# Delay consideration of block until PoW block is processed by the PoW node
|
||||
pow_block = get_pow_block(execution_payload.parent_hash)
|
||||
pow_parent = get_pow_block(pow_block.parent_hash)
|
||||
assert pow_block.is_processed
|
||||
assert is_valid_terminal_pow_block(transition_store, pow_block, pow_parent)
|
||||
def is_valid_terminal_pow_block(block: PowBlock, parent: PowBlock) -> bool:
|
||||
is_total_difficulty_reached = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
|
||||
is_parent_total_difficulty_valid = parent.total_difficulty < TERMINAL_TOTAL_DIFFICULTY
|
||||
return is_total_difficulty_reached and is_parent_total_difficulty_valid
|
||||
```
|
||||
|
||||
## Updated fork-choice handlers
|
||||
@ -127,7 +102,7 @@ def process_merge_execution_payload(transition_store: TransitionStore, execution
|
||||
*Note*: The only modification is the addition of the verification of transition block conditions.
|
||||
|
||||
```python
|
||||
def on_block(store: Store, signed_block: SignedBeaconBlock, transition_store: TransitionStore=None) -> None:
|
||||
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
||||
block = signed_block.message
|
||||
# Parent block must be known
|
||||
assert block.parent_root in store.block_states
|
||||
@ -142,13 +117,16 @@ def on_block(store: Store, signed_block: SignedBeaconBlock, transition_store: Tr
|
||||
# Check block is a descendant of the finalized block at the checkpoint finalized slot
|
||||
assert get_ancestor(store, block.parent_root, finalized_slot) == store.finalized_checkpoint.root
|
||||
|
||||
# [New in Merge]
|
||||
if (transition_store is not None) and is_merge_block(pre_state, block.body):
|
||||
process_merge_execution_payload(transition_store, block.body.execution_payload)
|
||||
|
||||
# Check the block is valid and compute the post-state
|
||||
state = pre_state.copy()
|
||||
state_transition(state, signed_block, True)
|
||||
|
||||
# [New in Merge]
|
||||
if is_merge_block(pre_state, block.body):
|
||||
pow_block = get_pow_block(block.body.execution_payload.parent_hash)
|
||||
pow_parent = get_pow_block(pow_block.parent_hash)
|
||||
assert is_valid_terminal_pow_block(pow_block, pow_parent)
|
||||
|
||||
# Add new block to the store
|
||||
store.blocks[hash_tree_root(block)] = block
|
||||
# Add new state for this block to the store
|
||||
|
@ -12,7 +12,6 @@
|
||||
- [Fork to Merge](#fork-to-merge)
|
||||
- [Fork trigger](#fork-trigger)
|
||||
- [Upgrading the state](#upgrading-the-state)
|
||||
- [Initializing transition store](#initializing-transition-store)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
@ -28,8 +27,6 @@ Warning: this configuration is not definitive.
|
||||
| - | - |
|
||||
| `MERGE_FORK_VERSION` | `Version('0x02000000')` |
|
||||
| `MERGE_FORK_EPOCH` | `Epoch(18446744073709551615)` **TBD** |
|
||||
| `MIN_ANCHOR_POW_BLOCK_DIFFICULTY` | `uint256(2 ** 32)` **TBD** |
|
||||
| `TARGET_SECONDS_TO_MERGE` | `uint64(7 * 86400)` = (604,800) |
|
||||
|
||||
## Fork to Merge
|
||||
|
||||
@ -37,8 +34,6 @@ Warning: this configuration is not definitive.
|
||||
|
||||
TBD. Social consensus, along with state conditions such as epoch boundary, finality, deposits, active validator count, etc. may be part of the decision process to trigger the fork. For now we assume the condition will be triggered at epoch `MERGE_FORK_EPOCH`.
|
||||
|
||||
Since the Merge transition process relies on `Eth1Data` in the beacon state we do want to make sure that this data is fresh. This is achieved by forcing `MERGE_FORK_EPOCH` to point to eth1 voting period boundary, i.e. `MERGE_FORK_EPOCH` should satisfy the following condition `MERGE_FORK_EPOCH % EPOCHS_PER_ETH1_VOTING_PERIOD == 0`.
|
||||
|
||||
Note that for the pure Merge networks, we don't apply `upgrade_to_merge` since it starts with Merge version logic.
|
||||
|
||||
### Upgrading the state
|
||||
@ -100,33 +95,3 @@ def upgrade_to_merge(pre: altair.BeaconState) -> BeaconState:
|
||||
|
||||
return post
|
||||
```
|
||||
|
||||
### Initializing transition store
|
||||
|
||||
If `state.slot % SLOTS_PER_EPOCH == 0`, `compute_epoch_at_slot(state.slot) == MERGE_FORK_EPOCH`, and the transition store has not already been initialized, a transition store is initialized to be further utilized by the transition process of the Merge.
|
||||
|
||||
Transition store initialization occurs after the state has been modified by corresponding `upgrade_to_merge` function.
|
||||
|
||||
```python
|
||||
def compute_terminal_total_difficulty(anchor_pow_block: PowBlock) -> uint256:
|
||||
seconds_per_voting_period = EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH * SECONDS_PER_SLOT
|
||||
pow_blocks_per_voting_period = seconds_per_voting_period // SECONDS_PER_ETH1_BLOCK
|
||||
pow_blocks_to_merge = TARGET_SECONDS_TO_MERGE // SECONDS_PER_ETH1_BLOCK
|
||||
pow_blocks_after_anchor_block = ETH1_FOLLOW_DISTANCE + pow_blocks_per_voting_period + pow_blocks_to_merge
|
||||
anchor_difficulty = max(MIN_ANCHOR_POW_BLOCK_DIFFICULTY, anchor_pow_block.difficulty)
|
||||
|
||||
return anchor_pow_block.total_difficulty + anchor_difficulty * uint256(pow_blocks_after_anchor_block)
|
||||
|
||||
|
||||
def get_transition_store(anchor_pow_block: PowBlock) -> TransitionStore:
|
||||
terminal_total_difficulty = compute_terminal_total_difficulty(anchor_pow_block)
|
||||
return TransitionStore(terminal_total_difficulty=terminal_total_difficulty)
|
||||
|
||||
|
||||
def initialize_transition_store(state: BeaconState) -> TransitionStore:
|
||||
pow_block = get_pow_block(state.eth1_data.block_hash)
|
||||
return get_transition_store(pow_block)
|
||||
```
|
||||
|
||||
*Note*: Transition store can also be initialized at client startup by [overriding terminal total
|
||||
difficulty](client_settings.md#override-terminal-total-difficulty).
|
||||
|
@ -62,7 +62,7 @@ All validator responsibilities remain unchanged other than those noted below. Na
|
||||
|
||||
##### Execution Payload
|
||||
|
||||
* Set `block.body.execution_payload = get_execution_payload(state, transition_store, execution_engine, pow_chain)` where:
|
||||
* Set `block.body.execution_payload = get_execution_payload(state, execution_engine, pow_chain)` where:
|
||||
|
||||
```python
|
||||
def get_pow_block_at_total_difficulty(total_difficulty: uint256, pow_chain: Sequence[PowBlock]) -> Optional[PowBlock]:
|
||||
@ -75,35 +75,27 @@ def get_pow_block_at_total_difficulty(total_difficulty: uint256, pow_chain: Sequ
|
||||
return None
|
||||
|
||||
|
||||
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)
|
||||
randao_mix = get_randao_mix(state, get_current_epoch(state))
|
||||
return execution_engine.assemble_block(parent_hash, timestamp, randao_mix)
|
||||
|
||||
|
||||
def get_execution_payload(state: BeaconState,
|
||||
transition_store: TransitionStore,
|
||||
randao_reveal: BLSSignature,
|
||||
execution_engine: ExecutionEngine,
|
||||
pow_chain: Sequence[PowBlock]) -> ExecutionPayload:
|
||||
if not is_merge_complete(state):
|
||||
terminal_pow_block = get_pow_block_at_total_difficulty(transition_store.terminal_total_difficulty, pow_chain)
|
||||
terminal_pow_block = get_pow_block_at_total_difficulty(TERMINAL_TOTAL_DIFFICULTY, pow_chain)
|
||||
if terminal_pow_block is None:
|
||||
# Pre-merge, empty payload
|
||||
return ExecutionPayload()
|
||||
else:
|
||||
# Signify merge via producing on top of the last PoW block
|
||||
return produce_execution_payload(state, terminal_pow_block.block_hash, randao_reveal, execution_engine)
|
||||
return produce_execution_payload(state, terminal_pow_block.block_hash, execution_engine)
|
||||
|
||||
# Post-merge, normal payload
|
||||
parent_hash = state.latest_execution_payload_header.block_hash
|
||||
return produce_execution_payload(state, parent_hash, randao_reveal, execution_engine)
|
||||
return produce_execution_payload(state, parent_hash, execution_engine)
|
||||
```
|
||||
|
@ -552,12 +552,12 @@ def compute_committee_index_from_shard(state: BeaconState, slot: Slot, shard: Sh
|
||||
```python
|
||||
def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
||||
process_block_header(state, block)
|
||||
# is_execution_enabled is omitted, execution is enabled by default.
|
||||
process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE)
|
||||
process_randao(state, block.body)
|
||||
process_eth1_data(state, block.body)
|
||||
process_operations(state, block.body) # [Modified in Sharding]
|
||||
process_sync_aggregate(state, block.body.sync_aggregate)
|
||||
# is_execution_enabled is omitted, execution is enabled by default.
|
||||
process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE)
|
||||
```
|
||||
|
||||
#### Operations
|
||||
|
@ -52,7 +52,7 @@ def test_process_light_client_update_not_updated(spec, state):
|
||||
sync_committee_signature = compute_aggregate_sync_committee_signature(
|
||||
spec,
|
||||
state,
|
||||
block.slot,
|
||||
block_header.slot,
|
||||
committee,
|
||||
)
|
||||
next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
|
||||
|
@ -100,8 +100,7 @@ def build_empty_block(spec, state, slot=None):
|
||||
empty_block.body.sync_aggregate.sync_committee_signature = spec.G2_POINT_AT_INFINITY
|
||||
|
||||
if is_post_merge(spec):
|
||||
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)
|
||||
empty_block.body.execution_payload = build_empty_execution_payload(spec, state)
|
||||
|
||||
return empty_block
|
||||
|
||||
|
@ -23,6 +23,7 @@ def build_empty_execution_payload(spec, state, randao_mix=None):
|
||||
gas_limit=latest.gas_limit, # retain same limit
|
||||
gas_used=0, # empty block, 0 gas
|
||||
timestamp=timestamp,
|
||||
extra_data=spec.ByteList[spec.MAX_EXTRA_DATA_BYTES](),
|
||||
base_fee_per_gas=latest.base_fee_per_gas, # retain same base_fee
|
||||
block_hash=spec.Hash32(),
|
||||
transactions=empty_txs,
|
||||
@ -45,6 +46,7 @@ def get_execution_payload_header(spec, execution_payload):
|
||||
gas_limit=execution_payload.gas_limit,
|
||||
gas_used=execution_payload.gas_used,
|
||||
timestamp=execution_payload.timestamp,
|
||||
extra_data=execution_payload.extra_data,
|
||||
base_fee_per_gas=execution_payload.base_fee_per_gas,
|
||||
block_hash=execution_payload.block_hash,
|
||||
transactions_root=spec.hash_tree_root(execution_payload.transactions)
|
||||
|
@ -148,6 +148,34 @@ def test_bad_parent_hash_regular_payload(spec, state):
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_bad_random_first_payload(spec, state):
|
||||
# pre-state
|
||||
state = build_state_with_incomplete_transition(spec, state)
|
||||
next_slot(spec, state)
|
||||
|
||||
# execution payload
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
execution_payload.random = b'\x42' * 32
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_bad_random_regular_payload(spec, state):
|
||||
# pre-state
|
||||
state = build_state_with_complete_transition(spec, state)
|
||||
next_slot(spec, state)
|
||||
|
||||
# execution payload
|
||||
execution_payload = build_empty_execution_payload(spec, state)
|
||||
execution_payload.random = b'\x04' * 32
|
||||
|
||||
yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
|
||||
|
||||
|
||||
@with_merge_and_later
|
||||
@spec_state_test
|
||||
def test_bad_number_regular_payload(spec, state):
|
||||
|
@ -143,6 +143,9 @@ def process_and_sign_block_without_header_validations(spec, state, block):
|
||||
state_root=spec.Bytes32(),
|
||||
body_root=block.body.hash_tree_root(),
|
||||
)
|
||||
if is_post_merge(spec):
|
||||
if spec.is_execution_enabled(state, block.body):
|
||||
spec.process_execution_payload(state, block.body.execution_payload, spec.EXECUTION_ENGINE)
|
||||
|
||||
# Perform rest of process_block transitions
|
||||
spec.process_randao(state, block.body)
|
||||
@ -150,9 +153,6 @@ def process_and_sign_block_without_header_validations(spec, state, block):
|
||||
spec.process_operations(state, block.body)
|
||||
if is_post_altair(spec):
|
||||
spec.process_sync_aggregate(state, block.body.sync_aggregate)
|
||||
if is_post_merge(spec):
|
||||
if spec.is_execution_enabled(state, block.body):
|
||||
spec.process_execution_payload(state, block.body.execution_payload, spec.EXECUTION_ENGINE)
|
||||
|
||||
# Insert post-state rot
|
||||
block.state_root = state.hash_tree_root()
|
||||
@ -196,8 +196,7 @@ def test_parent_from_same_slot(spec, state):
|
||||
child_block.parent_root = state.latest_block_header.hash_tree_root()
|
||||
|
||||
if is_post_merge(spec):
|
||||
randao_mix = spec.compute_randao_mix(state, child_block.body.randao_reveal)
|
||||
child_block.body.execution_payload = build_empty_execution_payload(spec, state, randao_mix)
|
||||
child_block.body.execution_payload = build_empty_execution_payload(spec, state)
|
||||
|
||||
# Show that normal path through transition fails
|
||||
failed_state = state.copy()
|
||||
|
Loading…
x
Reference in New Issue
Block a user