# BAL brain dump - Block builder must include all storage slots individual txs will access - This is consensus critical, so mismatching BAL lists will fail block validation - ExecutionPayloadV4 adds a blockAccessList field thats a RLP encoded BAL (So engine API gets a bump) - The builder has 2 phases: Collection phase and Build phase. Collection just records all touched state accesses. Build phase is encoding this info in RLP for consumption. - BALs should include the following: - Address wtih any state changes (storage, balance, nonce or code) - Addresses accessed without state changes: - targets of balance/extcodesize/extcodecopy/extcodehash opcode - targets of call, callcode, delegatecall, staticcall - target of create/create2 - tx sender and recipient (even for 0 value) - coinbase addy when receiving tx fees - beneficient addy for selfdestruct - system contract addy for pre/post exec - withdrawal recipient addy - precompile contracts touched - they need to be included even for 0 value OR when txs revert or creation fails for contracts (so basically if its ever interacted with then include it) - list must be lexicographic (byte wise) - `BlockAccessIndex`: `0` for **pre‑execution** system contract calls, 1..n for txs, n+1 for post-exec system calls - Address Deduplication: Each address appears only once, regardless of how many changes it has - tx_index is uint16 (https://eips.ethereum.org/assets/eip-7928/bal_size_analysis) questions: - What are pre-exec and post-exec system calls? - what is the max size a BAL can get to? can we chain together some null ops and see if we can make it significantly larger? - tx_index is uint16, can we overflow this somehow? ✅ (65k tx @ 21k gas is 1350M gas limit) - If worst case for BALs is that the optimisation is fully disabled (e.g uniswap pools filling the full block), then how do we plan on using any benefits of BALs for scaling? Do we ignore the attacks? Test ideas: - [x] happy path of including one of each type - [x] unhappy path of one of each revert or failed deployment (loop through reasons for failure too) - [x] contract deployment with too little gas (failed) - [x] try a 7702 call that will somehow use up over 16M gas (so the initial call that is gated by the RPC goes through, but the subsequent action it triggers should fail) - [x] have system contract address (withdrawal for e.g) be triggered by a 7702 delegated address - [x] attempt EXTCODECOPY via 7702 address - [x] ensure coinbase is included in BAL - [x] check calling blockhash precompile if it shows up in the BAL (seems like it should, but it wont trigger execution so easy to miss) - [x] trigger exec from addresses that are lexicographically similar, just endianness switched. It could catch some endian bugs. - [x] 7702 that triggers an SLOAD but it doesn't write anything - [x] tx that writes a storage slot to change its value, then a following tx that changes it back to the original value. Do this once with separate txs and once with a single tx. this should trigger edge cases in pre != post checks. - [N/A] SELFDESTRUCT where the balance is sent to a 7702 contract that then triggers some other execution? (is this possible?) - [] everything in the Edge case section of the EIP should have a test for it in EEST/Assertoor - [x] 7702 delegation failed tx - [x] check if the blockhash contract single updated storage slot is included properly - [x] withdrawals and deposits are subject to queue size and churn limits, test edge cases when this changes around - [?] reuse actions against one address and make sure that it doesnt get included twice by mistake - [] malicious block that provides fewer touched addresses than expected and observe all clients reject it - [] update the worst case block size table with worst case BALs # Stefan BAL Braindump # EIP-7928 Block-Level Access Lists (BALs) Testing Plan The following is a set of test cases first on a high level that we need to consider when creating tooling and our workloads. ## 1. Test Cases ### 1.1 Create & Create2 Collision Handling - CREATE to address with existing code - CREATE2 collision - CREATE that runs out of gas mid-deployment - CREATE where init code deploys multiple contracts - CREATE with empty init code - CREATE an account to an address with a balance that uses the balances. - CREATE with flash loans and then there is a self destruct ### 1.2 EVM fuzzing - Random Opcode sequences - Random call stack depth - NO-OP writes (write without changing the value) - Randomly have reverted transactions for different reasons - Out of gas - Invalid Opcode - Revert opcode - Require() / Assert() - Insufficient funds - Invalid Nonce - Exceeding call stack depth - Call pre-compiled contracts with random / empty values - Create a mix of independent and dependant transactions ### 1.3 Withdrawals [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) - [x] Withdrawal to address touched in transaction - [x] Withdrawal to contract with code - [x] Withdrawal to SELFDESTRUCT target - [x] Multiple withdrawals to same address - [] Zero-value withdrawal (via a bad block builder) - [x] Withrdawal to non-existing account ### 1.4 EIP-7702 delegation 1. Execute successful EIP-7702 delegation 2. Verify authority address has nonce and code changes 3. Test failed authorization with authority in accessed_addresses 4. Verify authority included with empty changes - Nonce change for delegated address without a balance change (otherwise a nonce change is always accompanied by a balance change) - Failed delegated transactions should not increase the nonce - EIP 7702 transactions don't fail if an auth does not go through. - Test OOG delegations - Test multiple auths within a single transaction for the same address - change the 7702 delegation to a new address - ### 1.5 Malicous Block builder Submit blocks with invalid BALs, which could catch errors in clients along the BAL validation code paths. ### 1.6 Chaos & Recovery Testing - Make sure that nodes can recover from any kind of failure and reorg back to the main chain. ### 1.7 Sync testing - test wether clients can sync back up to the latest head with BALs. - Test BAL generation with pre-BAL blocks - Verify stateless sync by only applying BALs state diffs. ### 1.8 Generate Worst Case Blocks - Maximum Sload operations - Many small transactions e.g. many 1 wei transactions ### 1.9 COINBASE handling. ### 1.10 BALANCE Edge Cases (Zero Balance Changes) - Account receives 1 ETH, sends 1 ETH in same tx → net zero - SELFDESTRUCT to address with 0 balance (same-tx created) - CALL with value to contract that immediately sends it back - Gas refund exactly equals gas cost (net zero balance change) - SELFDESCTRUCT to the self destructing contract address. With or without pre-balance. (CREATE2). - Pre-balance / no pre-balance edge cases - SELFDESTRUCT, send balance in the init code, SELFDESTRUCT to self. - Send to address A with a normal transaction. Use 7702 to delegate auth from A the same amount to B. ## 2. Root Cause Analysis - Use besu's bad block endpoint to compare the generatedBlockAccessList to the block.accessList of the bad block. - Query the extra data of the block `block.extraData` to identify who created the bad block - Use the difference to perform a analysis by requsting the transaction traces or block traces from the bad block producer. - Identify if besu is at fault or if the bad block producer is at fault. ## 3. Metrics When generating blocks with varying sizes how do BALs affect the network. ### Block processing time - Read time - Execution time ### Block proposal time - cost of added BAL generation time ### Block p2p transfer time - How the additional size affects network transfer times - Time to 50% nodes, time to ### Block size - How large is the BAL as a % of the block size. - Compression ratio ### Worst Cases - What is the worst case execution / validation time relative to the number of CPUs - Worst case BAL size ## 4. Tooling Updates ### 4.1 Assertoor Most test cases with assertoor should consist of running a workload such as a spamoor scenario and then checking if there are forks after the workload. #### Potential workloads: - EEST testing against devnet - EVM fuzzing - Contract creation edge cases - Withdrawals - EIP 7702 delegation - Sync test? - Balance Edge Cases ### 4.2 Spamoor - [x] evm-fuzz ### 4.3 Traceor - [x] If clients implement the `debug_getBadBlock` the same way that besu has then we only need to add a field to the [existing implementation](https://github.com/ethpandaops/tracoor/pull/52). - Link to the Dora diff view / add info regarding the dora BAL diff view. ### 4.4 Dora - [x] BAL Diff View - [x] BAL block view ### 4.5 Baloor (new tool) - Compares two block level access lists and returns the difference and classifies if its either over-tracking an address or oder tracking it. - - Uses execution node RPC endpoint to retrieve the debug_traceTransactions #### Available Tools - `classify_bug_type`: **START HERE** - Classify bug as Type 1 (under-tracking) or Type 2 (over-tracking) - `list_missing_accounts`: See which accounts are missing from Block BAL (Type 1) - `list_extra_accounts`: See which accounts are extra in Block BAL (Type 2) - `verify_zero_access`: **CRITICAL FOR TYPE 2** - Definitively prove account was NEVER accessed by checking ALL transactions - `list_transactions`: List all transactions in the block - `search_account_in_transactions`: Find where an account appears in transaction data - `get_transaction_details`: Get full transaction details including input data and access lists - `trace_transaction`: Trace with prestateTracer or callTracer to see account accesses - `trace_transaction_opcodes`: **CRITICAL FOR TYPE 1** - Get opcode-level trace to find exact opcode that accessed an account - `get_transaction_receipt`: Get receipt with status, gas, and contract address - `get_block_info`: Get block metadata ### Notes - For parallel execution the BAL is utilized. Dependencies where sequential execution would previously be necessary can be avoided by using the values in the BAL. -