diff --git a/configs/mainnet.yaml b/configs/mainnet.yaml index 5ad394c08..baf489739 100644 --- a/configs/mainnet.yaml +++ b/configs/mainnet.yaml @@ -94,3 +94,33 @@ PROPOSER_SCORE_BOOST: 40 DEPOSIT_CHAIN_ID: 1 DEPOSIT_NETWORK_ID: 1 DEPOSIT_CONTRACT_ADDRESS: 0x00000000219ab540356cBB839Cbe05303d7705Fa + + +# Networking +# --------------------------------------------------------------- +# `2**20` (= 1048576, 1 MiB) +GOSSIP_MAX_SIZE: 1048576 +# `2**10` (= 1024) +MAX_REQUEST_BLOCKS: 1024 +# `2**8` (= 256) +EPOCHS_PER_SUBNET_SUBSCRIPTION: 256 +# `MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2` (= 33024, ~5 months) +MIN_EPOCHS_FOR_BLOCK_REQUESTS: 33024 +# `2**20` (=1048576, 1 MiB) +MAX_CHUNK_SIZE: 1048576 +# 5s +TTFB_TIMEOUT: 5 +# 10s +RESP_TIMEOUT: 10 +ATTESTATION_PROPAGATION_SLOT_RANGE: 32 +# 500ms +MAXIMUM_GOSSIP_CLOCK_DISPARITY: 500 +MESSAGE_DOMAIN_INVALID_SNAPPY: 0x00000000 +MESSAGE_DOMAIN_VALID_SNAPPY: 0x01000000 +# 2 subnets per node +SUBNETS_PER_NODE: 2 +# 2**8 (= 64) +ATTESTATION_SUBNET_COUNT: 64 +ATTESTATION_SUBNET_EXTRA_BITS: 0 +# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS +ATTESTATION_SUBNET_PREFIX_BITS: 6 diff --git a/configs/minimal.yaml b/configs/minimal.yaml index 5895cfc70..43f1fc83f 100644 --- a/configs/minimal.yaml +++ b/configs/minimal.yaml @@ -95,3 +95,33 @@ DEPOSIT_CHAIN_ID: 5 DEPOSIT_NETWORK_ID: 5 # Configured on a per testnet basis DEPOSIT_CONTRACT_ADDRESS: 0x1234567890123456789012345678901234567890 + + +# Networking +# --------------------------------------------------------------- +# `2**20` (= 1048576, 1 MiB) +GOSSIP_MAX_SIZE: 1048576 +# `2**10` (= 1024) +MAX_REQUEST_BLOCKS: 1024 +# `2**8` (= 256) +EPOCHS_PER_SUBNET_SUBSCRIPTION: 256 +# [customized] `MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2` (= 272) +MIN_EPOCHS_FOR_BLOCK_REQUESTS: 272 +# `2**20` (=1048576, 1 MiB) +MAX_CHUNK_SIZE: 1048576 +# 5s +TTFB_TIMEOUT: 5 +# 10s +RESP_TIMEOUT: 10 +ATTESTATION_PROPAGATION_SLOT_RANGE: 32 +# 500ms +MAXIMUM_GOSSIP_CLOCK_DISPARITY: 500 +MESSAGE_DOMAIN_INVALID_SNAPPY: 0x00000000 +MESSAGE_DOMAIN_VALID_SNAPPY: 0x01000000 +# 2 subnets per node +SUBNETS_PER_NODE: 2 +# 2**8 (= 64) +ATTESTATION_SUBNET_COUNT: 64 +ATTESTATION_SUBNET_EXTRA_BITS: 0 +# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS +ATTESTATION_SUBNET_PREFIX_BITS: 6 diff --git a/setup.py b/setup.py index 12a561514..6013eff75 100644 --- a/setup.py +++ b/setup.py @@ -279,7 +279,7 @@ def get_spec(file_name: Path, preset: Dict[str, str], config: Dict[str, str], pr elif name in config: config_vars[name] = VariableDefinition(value_def.type_name, config[name], value_def.comment, None) else: - if name == 'ENDIANNESS': + if name in ('ENDIANNESS', 'KZG_ENDIANNESS'): # Deal with mypy Literal typing check value_def = _parse_value(name, value, type_hint='Final') constant_vars[name] = value_def @@ -1051,6 +1051,7 @@ class PySpecCommand(Command): specs/phase0/fork-choice.md specs/phase0/validator.md specs/phase0/weak-subjectivity.md + specs/phase0/p2p-interface.md """ if self.spec_fork in (ALTAIR, BELLATRIX, CAPELLA, DENEB, EIP6110): self.md_doc_paths += """ diff --git a/specs/_features/eip4788/validator.md b/specs/_features/eip4788/validator.md index 3140cdb21..11462bda1 100644 --- a/specs/_features/eip4788/validator.md +++ b/specs/_features/eip4788/validator.md @@ -64,27 +64,12 @@ parameter to the `PayloadAttributes`. ```python def prepare_execution_payload(state: BeaconState, - pow_chain: Dict[Hash32, PowBlock], safe_block_hash: Hash32, finalized_block_hash: Hash32, suggested_fee_recipient: ExecutionAddress, execution_engine: ExecutionEngine) -> Optional[PayloadId]: - if not is_merge_transition_complete(state): - is_terminal_block_hash_set = TERMINAL_BLOCK_HASH != Hash32() - is_activation_epoch_reached = get_current_epoch(state) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH - if is_terminal_block_hash_set and not is_activation_epoch_reached: - # Terminal block hash is set but activation epoch is not yet reached, no prepare payload call is needed - return None - - terminal_pow_block = get_terminal_pow_block(pow_chain) - if terminal_pow_block is None: - # Pre-merge, no prepare payload call is needed - return None - # Signify merge via producing on top of the terminal PoW block - parent_hash = terminal_pow_block.block_hash - else: - # Post-merge, normal payload - parent_hash = state.latest_execution_payload_header.block_hash + # Verify consistency of the parent hash with respect to the previous execution payload header + parent_hash = state.latest_execution_payload_header.block_hash # Set the forkchoice head and initiate the payload build process payload_attributes = PayloadAttributes( diff --git a/specs/_features/eip6110/beacon-chain.md b/specs/_features/eip6110/beacon-chain.md index 084f88f14..5f6fd99cf 100644 --- a/specs/_features/eip6110/beacon-chain.md +++ b/specs/_features/eip6110/beacon-chain.md @@ -176,9 +176,8 @@ class BeaconState(Container): ```python 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_ENGINE) # [Modified in EIP6110] + process_withdrawals(state, block.body.execution_payload) + 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] @@ -211,8 +210,7 @@ def process_operations(state: BeaconState, body: BeaconBlockBody) -> None: for_ops(body.bls_to_execution_changes, process_bls_to_execution_change) # [New in EIP6110] - if is_execution_enabled(state, body): - for_ops(body.execution_payload.deposit_receipts, process_deposit_receipt) + for_ops(body.execution_payload.deposit_receipts, process_deposit_receipt) ``` #### New `process_deposit_receipt` @@ -241,8 +239,7 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody, executi 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 + assert payload.parent_hash == state.latest_execution_payload_header.block_hash # Verify prev_randao assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state)) # Verify timestamp diff --git a/specs/_features/sharding/beacon-chain.md b/specs/_features/sharding/beacon-chain.md index 7d6df51aa..e67bc09ed 100644 --- a/specs/_features/sharding/beacon-chain.md +++ b/specs/_features/sharding/beacon-chain.md @@ -236,8 +236,7 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None: process_block_header(state, block) verify_builder_block_bid(state, block) process_sharded_data(state, block) - if is_execution_enabled(state, block.body): - process_execution_payload(state, block, EXECUTION_ENGINE) + process_execution_payload(state, block, EXECUTION_ENGINE) if not is_builder_block_slot(block.slot): process_randao(state, block.body) @@ -371,8 +370,7 @@ def process_execution_payload(state: BeaconState, block: BeaconBlock, execution_ payload = block.body.payload_data.value.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 + assert payload.parent_hash == state.latest_execution_payload_header.block_hash # Verify random assert payload.random == get_randao_mix(state, get_current_epoch(state)) # Verify timestamp diff --git a/specs/bellatrix/validator.md b/specs/bellatrix/validator.md index dea763cde..2900bd1f0 100644 --- a/specs/bellatrix/validator.md +++ b/specs/bellatrix/validator.md @@ -127,12 +127,13 @@ To obtain an execution payload, a block proposer building a block on top of a `s ```python def prepare_execution_payload(state: BeaconState, - pow_chain: Dict[Hash32, PowBlock], safe_block_hash: Hash32, finalized_block_hash: Hash32, suggested_fee_recipient: ExecutionAddress, - execution_engine: ExecutionEngine) -> Optional[PayloadId]: + execution_engine: ExecutionEngine, + pow_chain: Optional[Dict[Hash32, PowBlock]]=None) -> Optional[PayloadId]: if not is_merge_transition_complete(state): + assert pow_chain is not None is_terminal_block_hash_set = TERMINAL_BLOCK_HASH != Hash32() is_activation_epoch_reached = get_current_epoch(state) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH if is_terminal_block_hash_set and not is_activation_epoch_reached: diff --git a/specs/capella/beacon-chain.md b/specs/capella/beacon-chain.md index af4083017..0b5faf19c 100644 --- a/specs/capella/beacon-chain.md +++ b/specs/capella/beacon-chain.md @@ -331,9 +331,9 @@ def process_historical_summaries_update(state: BeaconState) -> None: ```python 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_ENGINE) # [Modified in Capella] + # [Modified in Capella] Removed `is_execution_enabled` check in Capella + process_withdrawals(state, block.body.execution_payload) # [New 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] @@ -404,15 +404,15 @@ def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None: #### Modified `process_execution_payload` -*Note*: The function `process_execution_payload` is modified to use the new `ExecutionPayloadHeader` type. +*Note*: The function `process_execution_payload` is modified to use the new `ExecutionPayloadHeader` type +and removed the `is_merge_transition_complete` check. ```python def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None: payload = body.execution_payload - + # [Modified in Capella] Removed `is_merge_transition_complete` check in Capella # 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 + assert payload.parent_hash == state.latest_execution_payload_header.block_hash # Verify prev_randao assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state)) # Verify timestamp diff --git a/specs/capella/fork-choice.md b/specs/capella/fork-choice.md index 0e0a393c3..87fec02f8 100644 --- a/specs/capella/fork-choice.md +++ b/specs/capella/fork-choice.md @@ -14,6 +14,8 @@ - [`notify_forkchoice_updated`](#notify_forkchoice_updated) - [Helpers](#helpers) - [Extended `PayloadAttributes`](#extended-payloadattributes) +- [Updated fork-choice handlers](#updated-fork-choice-handlers) + - [`on_block`](#on_block) @@ -60,3 +62,56 @@ class PayloadAttributes(object): suggested_fee_recipient: ExecutionAddress withdrawals: Sequence[Withdrawal] # [New in Capella] ``` + +## Updated fork-choice handlers + +### `on_block` + +*Note*: The only modification is the deletion of the verification of merge transition block conditions. + +```python +def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: + """ + Run ``on_block`` upon receiving a new block. + """ + block = signed_block.message + # Parent block must be known + assert block.parent_root in store.block_states + # Make a copy of the state to avoid mutability issues + pre_state = copy(store.block_states[block.parent_root]) + # Blocks cannot be in the future. If they are, their consideration must be delayed until they are in the past. + assert get_current_slot(store) >= block.slot + + # Check that block is later than the finalized epoch slot (optimization to reduce calls to get_ancestor) + finalized_slot = compute_start_slot_at_epoch(store.finalized_checkpoint.epoch) + assert block.slot > finalized_slot + # Check block is a descendant of the finalized block at the checkpoint finalized slot + finalized_checkpoint_block = get_checkpoint_block( + store, + block.parent_root, + store.finalized_checkpoint.epoch, + ) + assert store.finalized_checkpoint.root == finalized_checkpoint_block + + # Check the block is valid and compute the post-state + state = pre_state.copy() + block_root = hash_tree_root(block) + state_transition(state, signed_block, True) + + # Add new block to the store + store.blocks[block_root] = block + # Add new state for this block to the store + store.block_states[block_root] = state + + # Add proposer score boost if the block is timely + time_into_slot = (store.time - store.genesis_time) % SECONDS_PER_SLOT + is_before_attesting_interval = time_into_slot < SECONDS_PER_SLOT // INTERVALS_PER_SLOT + if get_current_slot(store) == block.slot and is_before_attesting_interval: + store.proposer_boost_root = hash_tree_root(block) + + # Update checkpoints in store if necessary + update_checkpoints(store, state.current_justified_checkpoint, state.finalized_checkpoint) + + # Eagerly compute unrealized justification and finality. + compute_pulled_up_tip(store, block_root) +``` diff --git a/specs/capella/validator.md b/specs/capella/validator.md index 29cff8c61..1015a95d7 100644 --- a/specs/capella/validator.md +++ b/specs/capella/validator.md @@ -79,27 +79,12 @@ That is, `state` is the `previous_state` processed through any empty slots up to ```python def prepare_execution_payload(state: BeaconState, - pow_chain: Dict[Hash32, PowBlock], safe_block_hash: Hash32, finalized_block_hash: Hash32, suggested_fee_recipient: ExecutionAddress, execution_engine: ExecutionEngine) -> Optional[PayloadId]: - if not is_merge_transition_complete(state): - is_terminal_block_hash_set = TERMINAL_BLOCK_HASH != Hash32() - is_activation_epoch_reached = get_current_epoch(state) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH - if is_terminal_block_hash_set and not is_activation_epoch_reached: - # Terminal block hash is set but activation epoch is not yet reached, no prepare payload call is needed - return None - - terminal_pow_block = get_terminal_pow_block(pow_chain) - if terminal_pow_block is None: - # Pre-merge, no prepare payload call is needed - return None - # Signify merge via producing on top of the terminal PoW block - parent_hash = terminal_pow_block.block_hash - else: - # Post-merge, normal payload - parent_hash = state.latest_execution_payload_header.block_hash + # [Modified in Capella] Removed `is_merge_transition_complete` check in Capella + parent_hash = state.latest_execution_payload_header.block_hash # Set the forkchoice head and initiate the payload build process payload_attributes = PayloadAttributes( diff --git a/specs/deneb/beacon-chain.md b/specs/deneb/beacon-chain.md index bffa6a456..5c31f1fc0 100644 --- a/specs/deneb/beacon-chain.md +++ b/specs/deneb/beacon-chain.md @@ -216,8 +216,7 @@ def process_execution_payload(state: BeaconState, body: BeaconBlockBody, executi 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 + assert payload.parent_hash == state.latest_execution_payload_header.block_hash # Verify prev_randao assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state)) # Verify timestamp diff --git a/specs/deneb/fork-choice.md b/specs/deneb/fork-choice.md index ce9973f13..c70a6e8d1 100644 --- a/specs/deneb/fork-choice.md +++ b/specs/deneb/fork-choice.md @@ -98,10 +98,6 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: block_root = hash_tree_root(block) state_transition(state, signed_block, True) - # Check the merge transition - if is_merge_transition_block(pre_state, block.body): - validate_merge_block(block) - # Add new block to the store store.blocks[block_root] = block # Add new state for this block to the store diff --git a/specs/deneb/polynomial-commitments.md b/specs/deneb/polynomial-commitments.md index 39758ac88..e800d8cc2 100644 --- a/specs/deneb/polynomial-commitments.md +++ b/specs/deneb/polynomial-commitments.md @@ -77,6 +77,7 @@ Public functions MUST accept raw bytes as input and perform the required cryptog | `BYTES_PER_FIELD_ELEMENT` | `uint64(32)` | Bytes used to encode a BLS scalar field element | | `BYTES_PER_BLOB` | `uint64(BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB)` | The number of bytes in a blob | | `G1_POINT_AT_INFINITY` | `Bytes48(b'\xc0' + b'\x00' * 47)` | Serialized form of the point at infinity on the G1 group | +| `KZG_ENDIANNESS` | `'big'` | The endianness of the field elements including blobs | ## Preset @@ -161,7 +162,7 @@ def hash_to_bls_field(data: bytes) -> BLSFieldElement: The output is not uniform over the BLS field. """ hashed_data = hash(data) - return BLSFieldElement(int.from_bytes(hashed_data, ENDIANNESS) % BLS_MODULUS) + return BLSFieldElement(int.from_bytes(hashed_data, KZG_ENDIANNESS) % BLS_MODULUS) ``` #### `bytes_to_bls_field` @@ -172,7 +173,7 @@ def bytes_to_bls_field(b: Bytes32) -> BLSFieldElement: Convert untrusted bytes to a trusted and validated BLS scalar field element. This function does not accept inputs greater than the BLS modulus. """ - field_element = int.from_bytes(b, ENDIANNESS) + field_element = int.from_bytes(b, KZG_ENDIANNESS) assert field_element < BLS_MODULUS return BLSFieldElement(field_element) ``` @@ -237,7 +238,7 @@ def compute_challenge(blob: Blob, """ # Append the degree of the polynomial as a domain separator - degree_poly = int.to_bytes(FIELD_ELEMENTS_PER_BLOB, 16, ENDIANNESS) + degree_poly = int.to_bytes(FIELD_ELEMENTS_PER_BLOB, 16, KZG_ENDIANNESS) data = FIAT_SHAMIR_PROTOCOL_DOMAIN + degree_poly data += blob @@ -406,15 +407,15 @@ def verify_kzg_proof_batch(commitments: Sequence[KZGCommitment], # Compute a random challenge. Note that it does not have to be computed from a hash, # r just has to be random. - degree_poly = int.to_bytes(FIELD_ELEMENTS_PER_BLOB, 8, ENDIANNESS) - num_commitments = int.to_bytes(len(commitments), 8, ENDIANNESS) + degree_poly = int.to_bytes(FIELD_ELEMENTS_PER_BLOB, 8, KZG_ENDIANNESS) + num_commitments = int.to_bytes(len(commitments), 8, KZG_ENDIANNESS) data = RANDOM_CHALLENGE_KZG_BATCH_DOMAIN + degree_poly + num_commitments # Append all inputs to the transcript before we hash for commitment, z, y, proof in zip(commitments, zs, ys, proofs): data += commitment \ - + int.to_bytes(z, BYTES_PER_FIELD_ELEMENT, ENDIANNESS) \ - + int.to_bytes(y, BYTES_PER_FIELD_ELEMENT, ENDIANNESS) \ + + int.to_bytes(z, BYTES_PER_FIELD_ELEMENT, KZG_ENDIANNESS) \ + + int.to_bytes(y, BYTES_PER_FIELD_ELEMENT, KZG_ENDIANNESS) \ + proof r = hash_to_bls_field(data) @@ -451,7 +452,7 @@ def compute_kzg_proof(blob: Blob, z_bytes: Bytes32) -> Tuple[KZGProof, Bytes32]: assert len(z_bytes) == BYTES_PER_FIELD_ELEMENT polynomial = blob_to_polynomial(blob) proof, y = compute_kzg_proof_impl(polynomial, bytes_to_bls_field(z_bytes)) - return proof, y.to_bytes(BYTES_PER_FIELD_ELEMENT, ENDIANNESS) + return proof, y.to_bytes(BYTES_PER_FIELD_ELEMENT, KZG_ENDIANNESS) ``` #### `compute_quotient_eval_within_domain` diff --git a/specs/phase0/p2p-interface.md b/specs/phase0/p2p-interface.md index 2503d906c..de3e0e529 100644 --- a/specs/phase0/p2p-interface.md +++ b/specs/phase0/p2p-interface.md @@ -20,6 +20,8 @@ It consists of four main sections: - [Protocol Negotiation](#protocol-negotiation) - [Multiplexing](#multiplexing) - [Consensus-layer network interaction domains](#consensus-layer-network-interaction-domains) + - [Custom types](#custom-types) + - [Constants](#constants) - [Configuration](#configuration) - [MetaData](#metadata) - [The gossip domain: gossipsub](#the-gossip-domain-gossipsub) @@ -53,6 +55,7 @@ It consists of four main sections: - [ENR structure](#enr-structure) - [Attestation subnet bitfield](#attestation-subnet-bitfield) - [`eth2` field](#eth2-field) + - [Attestation subnet subcription](#attestation-subnet-subcription) - [Design decision rationale](#design-decision-rationale) - [Transport](#transport-1) - [Why are we defining specific transports?](#why-are-we-defining-specific-transports) @@ -165,22 +168,42 @@ See the [Rationale](#design-decision-rationale) section below for tradeoffs. ## Consensus-layer network interaction domains +### Custom types + +We define the following Python custom types for type hinting and readability: + +| Name | SSZ equivalent | Description | +| - | - | - | +| `NodeID` | `uint256` | node identifier | +| `SubnetID` | `uint64` | subnet identifier | + +### Constants + +| Name | Value | Unit | Duration | +| - | - | :-: | :-: | +| `NODE_ID_BITS` | `256` | The bit length of uint256 is 256 | + ### Configuration -This section outlines constants that are used in this spec. +This section outlines configurations that are used in this spec. | Name | Value | Description | |---|---|---| | `GOSSIP_MAX_SIZE` | `2**20` (= 1048576, 1 MiB) | The maximum allowed size of uncompressed gossip messages. | | `MAX_REQUEST_BLOCKS` | `2**10` (= 1024) | Maximum number of blocks in a single request | +| `EPOCHS_PER_SUBNET_SUBSCRIPTION` | `2**8` (= 256) | Number of epochs on a subnet subscription (~27 hours) | | `MIN_EPOCHS_FOR_BLOCK_REQUESTS` | `MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2` (= 33024, ~5 months) | The minimum epoch range over which a node must serve blocks | -| `MAX_CHUNK_SIZE` | `2**20` (1048576, 1 MiB) | The maximum allowed size of uncompressed req/resp chunked responses. | -| `TTFB_TIMEOUT` | `5s` | The maximum time to wait for first byte of request response (time-to-first-byte). | -| `RESP_TIMEOUT` | `10s` | The maximum time for complete response transfer. | +| `MAX_CHUNK_SIZE` | `2**20` (=1048576, 1 MiB) | The maximum allowed size of uncompressed req/resp chunked responses. | +| `TTFB_TIMEOUT` | `5` | The maximum duration in **seconds** to wait for first byte of request response (time-to-first-byte). | +| `RESP_TIMEOUT` | `10` | The maximum duration in **seconds** for complete response transfer. | | `ATTESTATION_PROPAGATION_SLOT_RANGE` | `32` | The maximum number of slots during which an attestation can be propagated. | -| `MAXIMUM_GOSSIP_CLOCK_DISPARITY` | `500ms` | The maximum milliseconds of clock disparity assumed between honest nodes. | -| `MESSAGE_DOMAIN_INVALID_SNAPPY` | `0x00000000` | 4-byte domain for gossip message-id isolation of *invalid* snappy messages | -| `MESSAGE_DOMAIN_VALID_SNAPPY` | `0x01000000` | 4-byte domain for gossip message-id isolation of *valid* snappy messages | +| `MAXIMUM_GOSSIP_CLOCK_DISPARITY` | `500` | The maximum **milliseconds** of clock disparity assumed between honest nodes. | +| `MESSAGE_DOMAIN_INVALID_SNAPPY` | `DomainType('0x00000000')` | 4-byte domain for gossip message-id isolation of *invalid* snappy messages | +| `MESSAGE_DOMAIN_VALID_SNAPPY` | `DomainType('0x01000000')` | 4-byte domain for gossip message-id isolation of *valid* snappy messages | +| `SUBNETS_PER_NODE` | `2` | The number of long-lived subnets a beacon node should be subscribed to. | +| `ATTESTATION_SUBNET_COUNT` | `2**6` (= 64) | The number of attestation subnets used in the gossipsub protocol. | +| `ATTESTATION_SUBNET_EXTRA_BITS` | `0` | The number of extra bits of a NodeId to use when mapping to a subscribed subnet | +| `ATTESTATION_SUBNET_PREFIX_BITS` | `int(ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS)` | | ### MetaData @@ -979,6 +1002,34 @@ Clients MAY connect to peers with the same `fork_digest` but a different `next_f Unless `ENRForkID` is manually updated to matching prior to the earlier `next_fork_epoch` of the two clients, these connecting clients will be unable to successfully interact starting at the earlier `next_fork_epoch`. +### Attestation subnet subcription + +Because Phase 0 does not have shards and thus does not have Shard Committees, there is no stable backbone to the attestation subnets (`beacon_attestation_{subnet_id}`). To provide this stability, each beacon node should: + +* Remain subscribed to `SUBNETS_PER_NODE` for `EPOCHS_PER_SUBNET_SUBSCRIPTION` epochs. +* Maintain advertisement of the selected subnets in their node's ENR `attnets` entry by setting the selected `subnet_id` bits to `True` (e.g. `ENR["attnets"][subnet_id] = True`) for all persistent attestation subnets. +* Select these subnets based on their node-id as specified by the following `compute_subscribed_subnets(node_id, epoch)` function. + +```python +def compute_subscribed_subnet(node_id: NodeID, epoch: Epoch, index: int) -> SubnetID: + node_id_prefix = node_id >> (NODE_ID_BITS - ATTESTATION_SUBNET_PREFIX_BITS) + node_offset = node_id % EPOCHS_PER_SUBNET_SUBSCRIPTION + permutation_seed = hash(uint_to_bytes(uint64((epoch + node_offset) // EPOCHS_PER_SUBNET_SUBSCRIPTION))) + permutated_prefix = compute_shuffled_index( + node_id_prefix, + 1 << ATTESTATION_SUBNET_PREFIX_BITS, + permutation_seed, + ) + return SubnetID((permutated_prefix + index) % ATTESTATION_SUBNET_COUNT) +``` + +```python +def compute_subscribed_subnets(node_id: NodeID, epoch: Epoch) -> Sequence[SubnetID]: + return [compute_subscribed_subnet(node_id, epoch, index) for index in range(SUBNETS_PER_NODE)] +``` + +*Note*: When preparing for a hard fork, a node must select and subscribe to subnets of the future fork versioning at least `EPOCHS_PER_SUBNET_SUBSCRIPTION` epochs in advance of the fork. These new subnets for the fork are maintained in addition to those for the current fork until the fork occurs. After the fork occurs, let the subnets from the previous fork reach the end of life with no replacements. + ## Design decision rationale ### Transport @@ -1438,6 +1489,8 @@ the epoch range that a new node syncing from a checkpoint must backfill. [weak subjectivity guide](./weak-subjectivity.md). Specifically to find this max epoch range, we use the worst case event of a very large validator size (`>= MIN_PER_EPOCH_CHURN_LIMIT * CHURN_LIMIT_QUOTIENT`). +[0]: # (eth2spec: skip) + ```python MIN_EPOCHS_FOR_BLOCK_REQUESTS = ( MIN_VALIDATOR_WITHDRAWABILITY_DELAY diff --git a/specs/phase0/validator.md b/specs/phase0/validator.md index b0a9ac507..602df0973 100644 --- a/specs/phase0/validator.md +++ b/specs/phase0/validator.md @@ -10,7 +10,6 @@ This is an accompanying document to [Phase 0 -- The Beacon Chain](./beacon-chain - [Introduction](#introduction) - [Prerequisites](#prerequisites) -- [Custom types](#custom-types) - [Constants](#constants) - [Misc](#misc) - [Containers](#containers) @@ -64,7 +63,6 @@ This is an accompanying document to [Phase 0 -- The Beacon Chain](./beacon-chain - [Aggregation bits](#aggregation-bits-1) - [Aggregate signature](#aggregate-signature-1) - [Broadcast aggregate](#broadcast-aggregate) -- [Phase 0 attestation subnet stability](#phase-0-attestation-subnet-stability) - [How to avoid slashing](#how-to-avoid-slashing) - [Proposer slashing](#proposer-slashing) - [Attester slashing](#attester-slashing) @@ -83,15 +81,6 @@ A validator is an entity that participates in the consensus of the Ethereum proo All terminology, constants, functions, and protocol mechanics defined in the [Phase 0 -- The Beacon Chain](./beacon-chain.md) and [Phase 0 -- Deposit Contract](./deposit-contract.md) doc are requisite for this document and used throughout. Please see the Phase 0 doc before continuing and use as a reference throughout. -## Custom types - -We define the following Python custom types for type hinting and readability: - -| Name | SSZ equivalent | Description | -| - | - | - | -| `NodeID` | `uint256` | node identifier | -| `SubnetID` | `uint64` | subnet identifier | - ## Constants ### Misc @@ -99,12 +88,6 @@ We define the following Python custom types for type hinting and readability: | Name | Value | Unit | Duration | | - | - | :-: | :-: | | `TARGET_AGGREGATORS_PER_COMMITTEE` | `2**4` (= 16) | validators | -| `EPOCHS_PER_SUBNET_SUBSCRIPTION` | `2**8` (= 256) | epochs | ~27 hours | -| `ATTESTATION_SUBNET_COUNT` | `64` | The number of attestation subnets used in the gossipsub protocol. | -| `ATTESTATION_SUBNET_EXTRA_BITS` | `0` | The number of extra bits of a NodeId to use when mapping to a subscribed subnet | -| `SUBNETS_PER_NODE` | `2` | The number of long-lived subnets a beacon node should be subscribed to. | -| `ATTESTATION_SUBNET_PREFIX_BITS` | `(ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS)` | | -| `NODE_ID_BITS` | `256` | The bit length of uint256 is 256 | ## Containers @@ -619,34 +602,6 @@ def get_aggregate_and_proof_signature(state: BeaconState, return bls.Sign(privkey, signing_root) ``` -## Phase 0 attestation subnet stability - -Because Phase 0 does not have shards and thus does not have Shard Committees, there is no stable backbone to the attestation subnets (`beacon_attestation_{subnet_id}`). To provide this stability, each beacon node should: - -* Remain subscribed to `SUBNETS_PER_NODE` for `EPOCHS_PER_SUBNET_SUBSCRIPTION` epochs. -* Maintain advertisement of the selected subnets in their node's ENR `attnets` entry by setting the selected `subnet_id` bits to `True` (e.g. `ENR["attnets"][subnet_id] = True`) for all persistent attestation subnets. -* Select these subnets based on their node-id as specified by the following `compute_subscribed_subnets(node_id, epoch)` function. - -```python -def compute_subscribed_subnet(node_id: NodeID, epoch: Epoch, index: int) -> SubnetID: - node_id_prefix = node_id >> (NODE_ID_BITS - int(ATTESTATION_SUBNET_PREFIX_BITS)) - node_offset = node_id % EPOCHS_PER_SUBNET_SUBSCRIPTION - permutation_seed = hash(uint_to_bytes(uint64((epoch + node_offset) // EPOCHS_PER_SUBNET_SUBSCRIPTION))) - permutated_prefix = compute_shuffled_index( - node_id_prefix, - 1 << int(ATTESTATION_SUBNET_PREFIX_BITS), - permutation_seed, - ) - return SubnetID((permutated_prefix + index) % ATTESTATION_SUBNET_COUNT) -``` - -```python -def compute_subscribed_subnets(node_id: NodeID, epoch: Epoch) -> Sequence[SubnetID]: - return [compute_subscribed_subnet(node_id, epoch, index) for index in range(SUBNETS_PER_NODE)] -``` - -*Note*: When preparing for a hard fork, a validator must select and subscribe to subnets of the future fork versioning at least `EPOCHS_PER_SUBNET_SUBSCRIPTION` epochs in advance of the fork. These new subnets for the fork are maintained in addition to those for the current fork until the fork occurs. After the fork occurs, let the subnets from the previous fork reach the end of life with no replacements. - ## How to avoid slashing "Slashing" is the burning of some amount of validator funds and immediate ejection from the active validator set. In Phase 0, there are two ways in which funds can be slashed: [proposer slashing](#proposer-slashing) and [attester slashing](#attester-slashing). Although being slashed has serious repercussions, it is simple enough to avoid being slashed all together by remaining _consistent_ with respect to the messages a validator has previously signed. diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py index 1aa4a2c37..0f3a0b0b8 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py @@ -8,7 +8,13 @@ from eth2spec.test.helpers.execution_payload import ( build_state_with_incomplete_transition, build_state_with_complete_transition, ) -from eth2spec.test.context import spec_state_test, expect_assertion_error, with_bellatrix_and_later +from eth2spec.test.context import ( + BELLATRIX, + expect_assertion_error, + spec_state_test, + with_bellatrix_and_later, + with_phases, +) from eth2spec.test.helpers.state import next_slot @@ -119,7 +125,7 @@ def test_invalid_bad_execution_regular_payload(spec, state): yield from run_bad_execution_test(spec, state) -@with_bellatrix_and_later +@with_phases([BELLATRIX]) @spec_state_test def test_bad_parent_hash_first_payload(spec, state): state = build_state_with_incomplete_transition(spec, state) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/bellatrix/sanity/test_blocks.py index ef6bb75a9..75dfa0c9c 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/sanity/test_blocks.py @@ -10,7 +10,10 @@ from eth2spec.test.helpers.execution_payload import ( build_randomized_execution_payload ) from eth2spec.test.context import ( - with_bellatrix_and_later, spec_state_test + BELLATRIX, + with_bellatrix_and_later, + with_phases, + spec_state_test, ) @@ -44,7 +47,7 @@ def test_empty_block_transition_randomized_payload(spec, state): yield 'post', state -@with_bellatrix_and_later +@with_phases([BELLATRIX]) @spec_state_test def test_is_execution_enabled_false(spec, state): # Set `latest_execution_payload_header` to empty diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/unittests/validator/test_validator.py b/tests/core/pyspec/eth2spec/test/bellatrix/unittests/validator/test_validator.py index 6398aedd8..c55b6e3c3 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/unittests/validator/test_validator.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/unittests/validator/test_validator.py @@ -4,9 +4,12 @@ from typing import Optional from eth2spec.test.helpers.pow_block import ( prepare_random_pow_chain, ) +from eth2spec.test.helpers.constants import ( + BELLATRIX, +) from eth2spec.test.context import ( spec_state_test, - with_bellatrix_and_later, + with_phases, ) @@ -30,7 +33,7 @@ expected_results = [ # it would return the first block (IS_HEAD_PARENT_BLOCK). -@with_bellatrix_and_later +@with_phases([BELLATRIX]) @spec_state_test def test_get_pow_block_at_terminal_total_difficulty(spec, state): for result in expected_results: @@ -90,7 +93,7 @@ prepare_execution_payload_expected_results = [ ] -@with_bellatrix_and_later +@with_phases([BELLATRIX]) @spec_state_test def test_prepare_execution_payload(spec, state): for result in prepare_execution_payload_expected_results: @@ -157,11 +160,11 @@ def test_prepare_execution_payload(spec, state): payload_id = spec.prepare_execution_payload( state=state, - pow_chain=pow_chain.to_dict(), safe_block_hash=safe_block_hash, finalized_block_hash=finalized_block_hash, suggested_fee_recipient=suggested_fee_recipient, execution_engine=TestEngine(), + pow_chain=pow_chain.to_dict(), ) assert payload_id == result_payload_id diff --git a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_execution_payload.py new file mode 100644 index 000000000..1a2c1771a --- /dev/null +++ b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_execution_payload.py @@ -0,0 +1,24 @@ +from eth2spec.test.helpers.execution_payload import ( + build_empty_execution_payload, + compute_el_block_hash, + build_state_with_incomplete_transition, +) +from eth2spec.test.context import ( + spec_state_test, + with_capella_and_later, +) +from eth2spec.test.helpers.state import next_slot +from eth2spec.test.bellatrix.block_processing.test_process_execution_payload import run_execution_payload_processing + + +@with_capella_and_later +@spec_state_test +def test_invalid_bad_parent_hash_first_payload(spec, state): + state = build_state_with_incomplete_transition(spec, state) + next_slot(spec, state) + + execution_payload = build_empty_execution_payload(spec, state) + execution_payload.parent_hash = b'\x55' * 32 + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload) + + yield from run_execution_payload_processing(spec, state, execution_payload, valid=False) diff --git a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py index d62e458be..11d6f4e91 100644 --- a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py @@ -31,6 +31,29 @@ from eth2spec.test.helpers.deposits import ( from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits +# +# `is_execution_enabled` has been removed from Capella +# + +@with_capella_and_later +@spec_state_test +def test_invalid_is_execution_enabled_false(spec, state): + # Set `latest_execution_payload_header` to empty + state.latest_execution_payload_header = spec.ExecutionPayloadHeader() + yield 'pre', state + + block = build_empty_block_for_next_slot(spec, state) + + # Set `execution_payload` to empty + block.body.execution_payload = spec.ExecutionPayload() + assert len(block.body.execution_payload.transactions) == 0 + + signed_block = state_transition_and_sign_block(spec, state, block, expect_fail=True) + + yield 'blocks', [signed_block] + yield 'post', None + + # # BLSToExecutionChange # diff --git a/tests/core/pyspec/eth2spec/test/deneb/unittests/polynomial_commitments/test_polynomial_commitments.py b/tests/core/pyspec/eth2spec/test/deneb/unittests/polynomial_commitments/test_polynomial_commitments.py index 6d3f377a3..5ee8097c8 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/unittests/polynomial_commitments/test_polynomial_commitments.py +++ b/tests/core/pyspec/eth2spec/test/deneb/unittests/polynomial_commitments/test_polynomial_commitments.py @@ -33,7 +33,7 @@ def bls_add_one(x): def field_element_bytes(x): - return int.to_bytes(x % BLS_MODULUS, 32, "little") + return int.to_bytes(x % BLS_MODULUS, 32, "big") @with_deneb_and_later @@ -304,7 +304,7 @@ def test_bytes_to_bls_field_modulus_minus_one(spec): Verify that `bytes_to_bls_field` handles modulus minus one """ - spec.bytes_to_bls_field((BLS_MODULUS - 1).to_bytes(spec.BYTES_PER_FIELD_ELEMENT, spec.ENDIANNESS)) + spec.bytes_to_bls_field((BLS_MODULUS - 1).to_bytes(spec.BYTES_PER_FIELD_ELEMENT, spec.KZG_ENDIANNESS)) @with_deneb_and_later @@ -316,7 +316,7 @@ def test_bytes_to_bls_field_modulus(spec): """ expect_assertion_error(lambda: spec.bytes_to_bls_field( - BLS_MODULUS.to_bytes(spec.BYTES_PER_FIELD_ELEMENT, spec.ENDIANNESS) + BLS_MODULUS.to_bytes(spec.BYTES_PER_FIELD_ELEMENT, spec.KZG_ENDIANNESS) )) diff --git a/tests/core/pyspec/eth2spec/test/helpers/sharding.py b/tests/core/pyspec/eth2spec/test/helpers/sharding.py index 16b5a0234..32e1d4021 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/sharding.py +++ b/tests/core/pyspec/eth2spec/test/helpers/sharding.py @@ -58,7 +58,7 @@ def get_sample_blob(spec, rng=random.Random(5566), is_valid_blob=True): b = bytes() for v in values: - b += v.to_bytes(32, spec.ENDIANNESS) + b += v.to_bytes(32, spec.KZG_ENDIANNESS) return spec.Blob(b) diff --git a/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py b/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py index b0fd06374..6216ea2f0 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py +++ b/tests/core/pyspec/eth2spec/test/phase0/unittests/test_config_invariants.py @@ -75,7 +75,13 @@ def test_time(spec, state): @with_all_phases @spec_state_test def test_networking(spec, state): - assert spec.SUBNETS_PER_NODE <= spec.ATTESTATION_SUBNET_COUNT + assert spec.config.MIN_EPOCHS_FOR_BLOCK_REQUESTS == ( + spec.config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY + spec.config.CHURN_LIMIT_QUOTIENT // 2 + ) + assert spec.config.ATTESTATION_SUBNET_PREFIX_BITS == ( + spec.ceillog2(spec.config.ATTESTATION_SUBNET_COUNT) + spec.config.ATTESTATION_SUBNET_EXTRA_BITS + ) + assert spec.config.SUBNETS_PER_NODE <= spec.config.ATTESTATION_SUBNET_COUNT node_id_length = spec.NodeID(1).type_byte_length() # in bytes assert node_id_length * 8 == spec.NODE_ID_BITS # in bits diff --git a/tests/core/pyspec/eth2spec/test/phase0/unittests/validator/test_validator_unittest.py b/tests/core/pyspec/eth2spec/test/phase0/unittests/validator/test_validator_unittest.py index 177748eac..918ab96e2 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/unittests/validator/test_validator_unittest.py +++ b/tests/core/pyspec/eth2spec/test/phase0/unittests/validator/test_validator_unittest.py @@ -371,7 +371,7 @@ def test_compute_subnet_for_attestation(spec, state): slots_since_epoch_start = slot % spec.SLOTS_PER_EPOCH committees_since_epoch_start = committees_per_slot * slots_since_epoch_start - expected_subnet_id = (committees_since_epoch_start + committee_idx) % spec.ATTESTATION_SUBNET_COUNT + expected_subnet_id = (committees_since_epoch_start + committee_idx) % spec.config.ATTESTATION_SUBNET_COUNT assert actual_subnet_id == expected_subnet_id @@ -488,7 +488,7 @@ def run_compute_subscribed_subnets_arguments(spec, rng=random.Random(1111)): node_id = rng.randint(0, 2**40 - 1) # try VALIDATOR_REGISTRY_LIMIT epoch = rng.randint(0, 2**64 - 1) subnets = spec.compute_subscribed_subnets(node_id, epoch) - assert len(subnets) == spec.SUBNETS_PER_NODE + assert len(subnets) == spec.config.SUBNETS_PER_NODE @with_all_phases diff --git a/tests/formats/kzg/compute_kzg_proof.md b/tests/formats/kzg/compute_kzg_proof.md index 0713d50d8..b10105129 100644 --- a/tests/formats/kzg/compute_kzg_proof.md +++ b/tests/formats/kzg/compute_kzg_proof.md @@ -14,8 +14,8 @@ output: Tuple[KZGProof, Bytes32] -- The KZG proof and the value y = f(z) ``` - `blob` here is encoded as a string: hexadecimal encoding of `4096 * 32 = 131072` bytes, prefixed with `0x`. -- `z` here is encoded as a string: hexadecimal encoding of `32` bytes representing a little endian encoded field element, prefixed with `0x`. -- `y` here is encoded as a string: hexadecimal encoding of `32` bytes representing a little endian encoded field element, prefixed with `0x`. +- `z` here is encoded as a string: hexadecimal encoding of `32` bytes representing a big endian encoded field element, prefixed with `0x`. +- `y` here is encoded as a string: hexadecimal encoding of `32` bytes representing a big endian encoded field element, prefixed with `0x`. All byte(s) fields are encoded as strings, hexadecimal encoding, prefixed with `0x`. diff --git a/tests/formats/kzg/verify_kzg_proof.md b/tests/formats/kzg/verify_kzg_proof.md index 143466b66..18e02710c 100644 --- a/tests/formats/kzg/verify_kzg_proof.md +++ b/tests/formats/kzg/verify_kzg_proof.md @@ -15,8 +15,8 @@ input: output: bool -- true (valid proof) or false (incorrect proof) ``` -- `z` here is encoded as a string: hexadecimal encoding of `32` bytes representing a little endian encoded field element, prefixed with `0x`. -- `y` here is encoded as a string: hexadecimal encoding of `32` bytes representing a little endian encoded field element, prefixed with `0x`. +- `z` here is encoded as a string: hexadecimal encoding of `32` bytes representing a big endian encoded field element, prefixed with `0x`. +- `y` here is encoded as a string: hexadecimal encoding of `32` bytes representing a big endian encoded field element, prefixed with `0x`. All byte(s) fields are encoded as strings, hexadecimal encoding, prefixed with `0x`. diff --git a/tests/generators/kzg_4844/main.py b/tests/generators/kzg_4844/main.py index 2f3efeb21..9297e524a 100644 --- a/tests/generators/kzg_4844/main.py +++ b/tests/generators/kzg_4844/main.py @@ -27,11 +27,11 @@ def expect_exception(func, *args): def field_element_bytes(x): - return int.to_bytes(x % spec.BLS_MODULUS, 32, spec.ENDIANNESS) + return int.to_bytes(x % spec.BLS_MODULUS, 32, spec.KZG_ENDIANNESS) def field_element_bytes_unchecked(x): - return int.to_bytes(x, 32, spec.ENDIANNESS) + return int.to_bytes(x, 32, spec.KZG_ENDIANNESS) def encode_hex_list(a): @@ -54,7 +54,7 @@ def evaluate_blob_at(blob, z): ) -BLS_MODULUS_BYTES = spec.BLS_MODULUS.to_bytes(32, spec.ENDIANNESS) +BLS_MODULUS_BYTES = spec.BLS_MODULUS.to_bytes(32, spec.KZG_ENDIANNESS) G1 = bls.G1_to_bytes48(bls.G1()) G1_INVALID_TOO_FEW_BYTES = G1[:-1] diff --git a/tests/generators/operations/main.py b/tests/generators/operations/main.py index 293bcdea7..7aea6fc6f 100644 --- a/tests/generators/operations/main.py +++ b/tests/generators/operations/main.py @@ -30,8 +30,9 @@ if __name__ == "__main__": bellatrix_mods = combine_mods(_new_bellatrix_mods, altair_mods) _new_capella_mods = {key: 'eth2spec.test.capella.block_processing.test_process_' + key for key in [ - 'deposit', 'bls_to_execution_change', + 'deposit', + 'execution_payload', 'withdrawals', ]} capella_mods = combine_mods(_new_capella_mods, bellatrix_mods)