diff --git a/tests/unscheduled/eip7928_block_level_access_lists/__init__.py b/tests/unscheduled/eip7928_block_level_access_lists/__init__.py new file mode 100644 index 00000000000..2f715be28c3 --- /dev/null +++ b/tests/unscheduled/eip7928_block_level_access_lists/__init__.py @@ -0,0 +1 @@ +"""Tests for [EIP-7928: Block-level Access Lists](https://eips.ethereum.org/EIPS/eip-7928).""" diff --git a/tests/unscheduled/eip7928_block_level_access_lists/spec.py b/tests/unscheduled/eip7928_block_level_access_lists/spec.py new file mode 100644 index 00000000000..56b4a954ad2 --- /dev/null +++ b/tests/unscheduled/eip7928_block_level_access_lists/spec.py @@ -0,0 +1,44 @@ +"""Reference spec for [EIP-7928: Block-level Access Lists.](https://eips.ethereum.org/EIPS/eip-7928).""" + +from dataclasses import dataclass + + +@dataclass(frozen=True) +class ReferenceSpec: + """Reference specification.""" + + git_path: str + version: str + + +ref_spec_7928 = ReferenceSpec( + git_path="EIPS/eip-7928.md", + version="35732baa14cfea785d9c58d5f18033392b7ed886", +) + + +@dataclass(frozen=True) +class Spec: + """Constants and parameters from EIP-7928.""" + + # SSZ encoding is used for block access list data structures + BAL_ENCODING_FORMAT: str = "SSZ" + + # Maximum limits for block access list data structures + TARGET_MAX_GAS_LIMIT = 600_000_000 + MAX_TXS: int = 30_000 + MAX_SLOTS: int = 300_000 + MAX_ACCOUNTS: int = 300_000 + # TODO: Use this as a function of the current fork. + MAX_CODE_SIZE: int = 24_576 # 24 KiB + + # Type size constants + ADDRESS_SIZE: int = 20 # Ethereum address size in bytes + STORAGE_KEY_SIZE: int = 32 # Storage slot key size in bytes + STORAGE_VALUE_SIZE: int = 32 # Storage value size in bytes + HASH_SIZE: int = 32 # Hash size in bytes + + # Numeric type limits + MAX_TX_INDEX: int = 2**16 - 1 # uint16 max value + MAX_BALANCE: int = 2**128 - 1 # uint128 max value + MAX_NONCE: int = 2**64 - 1 # uint64 max value diff --git a/tests/unscheduled/eip7928_block_level_access_lists/test_validate_bal.py b/tests/unscheduled/eip7928_block_level_access_lists/test_validate_bal.py new file mode 100644 index 00000000000..6557733aefb --- /dev/null +++ b/tests/unscheduled/eip7928_block_level_access_lists/test_validate_bal.py @@ -0,0 +1,416 @@ +"""Tests for validating EIP-7928: Block-level Access Lists (BAL).""" + +import pytest + +from ethereum_test_tools import ( + Alloc, + BlockchainTestFiller, +) + + +@pytest.mark.valid_from("Amsterdam") +class TestBALValidity: + """Test BAL validity and data structure integrity.""" + + def test_bal_hash_basic_transaction( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL hash generation for basic ETH transfer.""" + # TODO: Implement BAL hash validation for basic ETH transfer + pass + + def test_bal_hash_storage_operations( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL hash generation for storage read/write operations.""" + # TODO: Implement BAL hash validation for storage operations + pass + + def test_bal_hash_balance_changes( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL hash generation for balance changes.""" + # TODO: Implement BAL hash validation for balance changes + pass + + def test_bal_hash_nonce_changes( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL hash generation for nonce changes.""" + # TODO: Implement BAL hash validation for nonce changes + pass + + def test_bal_hash_code_changes( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL hash generation for contract code changes (CREATE/CREATE2).""" + # TODO: Implement BAL hash validation for code changes + pass + + def test_bal_ordering_requirements( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test that BAL entries follow strict address and storage key ordering.""" + # TODO: Implement ordering validation tests + pass + + def test_bal_completeness_validation( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test that BAL includes all accessed accounts and storage slots.""" + # TODO: Implement completeness validation tests + pass + + def test_bal_empty_block( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL hash generation for empty blocks (only coinbase access).""" + # TODO: Implement empty block BAL validation + pass + + def test_bal_multiple_transactions( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL hash generation for blocks with multiple transactions.""" + # TODO: Implement multiple transaction BAL validation + pass + + def test_bal_failed_transaction_inclusion( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test that failed transactions still contribute to BAL.""" + # TODO: Implement failed transaction BAL inclusion tests + pass + + +@pytest.mark.valid_from("Amsterdam") +class TestBALEncoding: + """Test SSZ encoding/decoding of BAL data structures.""" + + def test_ssz_encoding_storage_changes( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test SSZ round-trip encoding for storage changes.""" + # TODO: Implement SSZ encoding tests for storage changes + pass + + def test_ssz_encoding_balance_changes( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test SSZ round-trip encoding for balance changes.""" + # TODO: Implement SSZ encoding tests for balance changes + pass + + def test_ssz_encoding_nonce_changes( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test SSZ round-trip encoding for nonce changes.""" + # TODO: Implement SSZ encoding tests for nonce changes + pass + + def test_ssz_encoding_code_changes( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test SSZ round-trip encoding for code changes.""" + # TODO: Implement SSZ encoding tests for code changes + pass + + def test_ssz_encoding_full_bal( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test SSZ round-trip encoding for complete BAL structure.""" + # TODO: Implement full BAL SSZ encoding tests + pass + + +@pytest.mark.valid_from("Amsterdam") +class TestBALEdgeCases: + """Test edge cases and error conditions for BAL.""" + + def test_bal_large_storage_operations( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL with large numbers of storage operations.""" + # TODO: Implement large storage operation tests + pass + + def test_bal_contract_selfdestruct( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL handling of contract self-destruct operations.""" + # TODO: Implement self-destruct BAL tests + pass + + def test_bal_create2_deterministic_addresses( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL with CREATE2 deterministic contract addresses.""" + # TODO: Implement CREATE2 BAL tests + pass + + def test_bal_zero_value_changes( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL handling of zero-value state changes.""" + # TODO: Implement zero-value change tests + pass + + def test_bal_maximum_block_size( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL with maximum possible block size and access patterns.""" + # TODO: Implement maximum block size BAL tests + pass + + +@pytest.mark.valid_from("Amsterdam") +class TestBALValidationFailures: + """Test validation failure scenarios for malformed or incorrect BALs.""" + + def test_invalid_bal_hash_rejection( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test that blocks with invalid BAL hashes are rejected.""" + # TODO: Implement invalid BAL hash rejection tests + pass + + def test_incomplete_bal_rejection( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test that blocks with incomplete BALs are rejected.""" + # TODO: Implement incomplete BAL rejection tests + pass + + def test_incorrect_ordering_rejection( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test that blocks with incorrectly ordered BAL entries are rejected.""" + # TODO: Implement incorrect ordering rejection tests + pass + + def test_malformed_ssz_rejection( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test that blocks with malformed SSZ-encoded BALs are rejected.""" + # TODO: Implement malformed SSZ rejection tests + pass + + +@pytest.mark.valid_from("Amsterdam") +class TestBALLimits: + """Test EIP-7928 specification limits and boundaries.""" + + def test_max_transactions_limit( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation with MAX_TXS transactions per block.""" + # TODO: Test with Spec.MAX_TXS (30,000) transactions + pass + + def test_max_accounts_limit( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation with MAX_ACCOUNTS accessed accounts.""" + # TODO: Test with Spec.MAX_ACCOUNTS (300,000) accessed accounts + pass + + def test_max_storage_slots_limit( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation with MAX_SLOTS storage slots accessed.""" + # TODO: Test with Spec.MAX_SLOTS (300,000) storage slots + pass + + def test_max_code_size_limit( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation with MAX_CODE_SIZE contract deployments.""" + # TODO: Test with Spec.MAX_CODE_SIZE (24,576 bytes) contract code + pass + + def test_max_tx_index_boundary( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation at MAX_TX_INDEX boundary.""" + # TODO: Test with transaction index at Spec.MAX_TX_INDEX (65,535) + pass + + def test_max_balance_boundary( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation with MAX_BALANCE values.""" + # TODO: Test with balance at Spec.MAX_BALANCE (2^128 - 1) + pass + + def test_max_nonce_boundary( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation with MAX_NONCE values.""" + # TODO: Test with nonce at Spec.MAX_NONCE (2^64 - 1) + pass + + def test_target_max_gas_limit_boundary( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation at TARGET_MAX_GAS_LIMIT.""" + # TODO: Test with block gas limit at Spec.TARGET_MAX_GAS_LIMIT (600,000,000) + pass + + def test_address_size_validation( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation with ADDRESS_SIZE requirements.""" + # TODO: Test address size validation (Spec.ADDRESS_SIZE = 20 bytes) + pass + + def test_storage_key_size_validation( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation with STORAGE_KEY_SIZE requirements.""" + # TODO: Test storage key size validation (Spec.STORAGE_KEY_SIZE = 32 bytes) + pass + + def test_storage_value_size_validation( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation with STORAGE_VALUE_SIZE requirements.""" + # TODO: Test storage value size validation (Spec.STORAGE_VALUE_SIZE = 32 bytes) + pass + + def test_hash_size_validation( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation with HASH_SIZE requirements.""" + # TODO: Test BAL hash size validation (Spec.HASH_SIZE = 32 bytes) + pass + + +@pytest.mark.valid_from("Amsterdam") +class TestBALBoundaryConditions: + """Test boundary conditions and edge cases for EIP-7928 limits.""" + + def test_exceed_max_transactions( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL rejection when exceeding MAX_TXS.""" + # TODO: Test rejection with Spec.MAX_TXS + 1 transactions + pass + + def test_exceed_max_accounts( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL rejection when exceeding MAX_ACCOUNTS.""" + # TODO: Test rejection with Spec.MAX_ACCOUNTS + 1 accounts + pass + + def test_exceed_max_storage_slots( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL rejection when exceeding MAX_SLOTS.""" + # TODO: Test rejection with Spec.MAX_SLOTS + 1 storage slots + pass + + def test_exceed_max_code_size( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL rejection when exceeding MAX_CODE_SIZE.""" + # TODO: Test rejection with Spec.MAX_CODE_SIZE + 1 byte contract + pass + + def test_zero_values_at_boundaries( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation with zero values at type boundaries.""" + # TODO: Test with zero balances, nonces, and transaction indices + pass + + def test_minimum_valid_values( + self, + pre: Alloc, + blockchain_test: BlockchainTestFiller, + ): + """Test BAL validation with minimum valid values.""" + # TODO: Test with minimum valid balances, nonces, and indices + pass