ethereum.shanghai.fork
Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^
.. contents:: Table of Contents :backlinks: none :local:
Introduction
Entry point for the Ethereum specification.
1""" 2Ethereum Specification 3^^^^^^^^^^^^^^^^^^^^^^ 4 5.. contents:: Table of Contents 6 :backlinks: none 7 :local: 8 9Introduction 10------------ 11 12Entry point for the Ethereum specification. 13""" 14 15from dataclasses import dataclass 16from typing import List, Optional, Tuple, Union 17 18from ethereum.base_types import Bytes0, Bytes32 19from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover 20from ethereum.crypto.hash import Hash32, keccak256 21from ethereum.exceptions import InvalidBlock 22from ethereum.utils.ensure import ensure 23 24from .. import rlp 25from ..base_types import U64, U256, Bytes, Uint 26from . import vm 27from .bloom import logs_bloom 28from .fork_types import ( 29 TX_ACCESS_LIST_ADDRESS_COST, 30 TX_ACCESS_LIST_STORAGE_KEY_COST, 31 TX_BASE_COST, 32 TX_CREATE_COST, 33 TX_DATA_COST_PER_NON_ZERO, 34 TX_DATA_COST_PER_ZERO, 35 AccessListTransaction, 36 Address, 37 Block, 38 Bloom, 39 FeeMarketTransaction, 40 Header, 41 LegacyTransaction, 42 Log, 43 Receipt, 44 Root, 45 Transaction, 46 Withdrawal, 47 decode_transaction, 48 encode_transaction, 49) 50from .state import ( 51 State, 52 account_exists_and_is_empty, 53 destroy_account, 54 get_account, 55 increment_nonce, 56 process_withdrawal, 57 set_account_balance, 58 state_root, 59) 60from .trie import Trie, root, trie_set 61from .utils.message import prepare_message 62from .vm.gas import init_code_cost 63from .vm.interpreter import MAX_CODE_SIZE, process_message_call 64 65BASE_FEE_MAX_CHANGE_DENOMINATOR = 8 66ELASTICITY_MULTIPLIER = 2 67GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 68GAS_LIMIT_MINIMUM = 5000 69EMPTY_OMMER_HASH = keccak256(rlp.encode([])) 70 71 72@dataclass 73class BlockChain: 74 """ 75 History and current state of the block chain. 76 """ 77 78 blocks: List[Block] 79 state: State 80 chain_id: U64 81 82 83def apply_fork(old: BlockChain) -> BlockChain: 84 """ 85 Transforms the state from the previous hard fork (`old`) into the block 86 chain object for this hard fork and returns it. 87 88 When forks need to implement an irregular state transition, this function 89 is used to handle the irregularity. See the :ref:`DAO Fork <dao-fork>` for 90 an example. 91 92 Parameters 93 ---------- 94 old : 95 Previous block chain object. 96 97 Returns 98 ------- 99 new : `BlockChain` 100 Upgraded block chain object for this hard fork. 101 """ 102 return old 103 104 105def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: 106 """ 107 Obtain the list of hashes of the previous 256 blocks in order of 108 increasing block number. 109 110 This function will return less hashes for the first 256 blocks. 111 112 The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, 113 therefore this function retrieves them. 114 115 Parameters 116 ---------- 117 chain : 118 History and current state. 119 120 Returns 121 ------- 122 recent_block_hashes : `List[Hash32]` 123 Hashes of the recent 256 blocks in order of increasing block number. 124 """ 125 recent_blocks = chain.blocks[-255:] 126 # TODO: This function has not been tested rigorously 127 if len(recent_blocks) == 0: 128 return [] 129 130 recent_block_hashes = [] 131 132 for block in recent_blocks: 133 prev_block_hash = block.header.parent_hash 134 recent_block_hashes.append(prev_block_hash) 135 136 # We are computing the hash only for the most recent block and not for 137 # the rest of the blocks as they have successors which have the hash of 138 # the current block as parent hash. 139 most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) 140 recent_block_hashes.append(most_recent_block_hash) 141 142 return recent_block_hashes 143 144 145def state_transition(chain: BlockChain, block: Block) -> None: 146 """ 147 Attempts to apply a block to an existing block chain. 148 149 All parts of the block's contents need to be verified before being added 150 to the chain. Blocks are verified by ensuring that the contents of the 151 block make logical sense with the contents of the parent block. The 152 information in the block's header must also match the corresponding 153 information in the block. 154 155 To implement Ethereum, in theory clients are only required to store the 156 most recent 255 blocks of the chain since as far as execution is 157 concerned, only those blocks are accessed. Practically, however, clients 158 should store more blocks to handle reorgs. 159 160 Parameters 161 ---------- 162 chain : 163 History and current state. 164 block : 165 Block to apply to `chain`. 166 """ 167 parent_header = chain.blocks[-1].header 168 validate_header(block.header, parent_header) 169 ensure(block.ommers == (), InvalidBlock) 170 ( 171 gas_used, 172 transactions_root, 173 receipt_root, 174 block_logs_bloom, 175 state, 176 withdrawals_root, 177 ) = apply_body( 178 chain.state, 179 get_last_256_block_hashes(chain), 180 block.header.coinbase, 181 block.header.number, 182 block.header.base_fee_per_gas, 183 block.header.gas_limit, 184 block.header.timestamp, 185 block.header.prev_randao, 186 block.transactions, 187 chain.chain_id, 188 block.withdrawals, 189 ) 190 ensure(gas_used == block.header.gas_used, InvalidBlock) 191 ensure(transactions_root == block.header.transactions_root, InvalidBlock) 192 ensure(state_root(state) == block.header.state_root, InvalidBlock) 193 ensure(receipt_root == block.header.receipt_root, InvalidBlock) 194 ensure(block_logs_bloom == block.header.bloom, InvalidBlock) 195 ensure(withdrawals_root == block.header.withdrawals_root, InvalidBlock) 196 197 chain.blocks.append(block) 198 if len(chain.blocks) > 255: 199 # Real clients have to store more blocks to deal with reorgs, but the 200 # protocol only requires the last 255 201 chain.blocks = chain.blocks[-255:] 202 203 204def calculate_base_fee_per_gas( 205 block_gas_limit: Uint, 206 parent_gas_limit: Uint, 207 parent_gas_used: Uint, 208 parent_base_fee_per_gas: Uint, 209) -> Uint: 210 """ 211 Calculates the base fee per gas for the block. 212 213 Parameters 214 ---------- 215 block_gas_limit : 216 Gas limit of the block for which the base fee is being calculated. 217 parent_gas_limit : 218 Gas limit of the parent block. 219 parent_gas_used : 220 Gas used in the parent block. 221 parent_base_fee_per_gas : 222 Base fee per gas of the parent block. 223 224 Returns 225 ------- 226 base_fee_per_gas : `Uint` 227 Base fee per gas for the block. 228 """ 229 parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER 230 231 ensure( 232 check_gas_limit(block_gas_limit, parent_gas_limit), 233 InvalidBlock, 234 ) 235 236 if parent_gas_used == parent_gas_target: 237 expected_base_fee_per_gas = parent_base_fee_per_gas 238 elif parent_gas_used > parent_gas_target: 239 gas_used_delta = parent_gas_used - parent_gas_target 240 241 parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta 242 target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target 243 244 base_fee_per_gas_delta = max( 245 target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR, 246 1, 247 ) 248 249 expected_base_fee_per_gas = ( 250 parent_base_fee_per_gas + base_fee_per_gas_delta 251 ) 252 else: 253 gas_used_delta = parent_gas_target - parent_gas_used 254 255 parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta 256 target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target 257 258 base_fee_per_gas_delta = ( 259 target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR 260 ) 261 262 expected_base_fee_per_gas = ( 263 parent_base_fee_per_gas - base_fee_per_gas_delta 264 ) 265 266 return Uint(expected_base_fee_per_gas) 267 268 269def validate_header(header: Header, parent_header: Header) -> None: 270 """ 271 Verifies a block header. 272 273 In order to consider a block's header valid, the logic for the 274 quantities in the header should match the logic for the block itself. 275 For example the header timestamp should be greater than the block's parent 276 timestamp because the block was created *after* the parent block. 277 Additionally, the block's number should be directly following the parent 278 block's number since it is the next block in the sequence. 279 280 Parameters 281 ---------- 282 header : 283 Header to check for correctness. 284 parent_header : 285 Parent Header of the header to check for correctness 286 """ 287 ensure(header.gas_used <= header.gas_limit, InvalidBlock) 288 289 expected_base_fee_per_gas = calculate_base_fee_per_gas( 290 header.gas_limit, 291 parent_header.gas_limit, 292 parent_header.gas_used, 293 parent_header.base_fee_per_gas, 294 ) 295 296 ensure(expected_base_fee_per_gas == header.base_fee_per_gas, InvalidBlock) 297 298 ensure(header.timestamp > parent_header.timestamp, InvalidBlock) 299 ensure(header.number == parent_header.number + 1, InvalidBlock) 300 ensure(len(header.extra_data) <= 32, InvalidBlock) 301 302 ensure(header.difficulty == 0, InvalidBlock) 303 ensure(header.nonce == b"\x00\x00\x00\x00\x00\x00\x00\x00", InvalidBlock) 304 ensure(header.ommers_hash == EMPTY_OMMER_HASH, InvalidBlock) 305 306 block_parent_hash = keccak256(rlp.encode(parent_header)) 307 ensure(header.parent_hash == block_parent_hash, InvalidBlock) 308 309 310def check_transaction( 311 tx: Transaction, 312 base_fee_per_gas: Uint, 313 gas_available: Uint, 314 chain_id: U64, 315) -> Tuple[Address, Uint]: 316 """ 317 Check if the transaction is includable in the block. 318 319 Parameters 320 ---------- 321 tx : 322 The transaction. 323 base_fee_per_gas : 324 The block base fee. 325 gas_available : 326 The gas remaining in the block. 327 chain_id : 328 The ID of the current chain. 329 330 Returns 331 ------- 332 sender_address : 333 The sender of the transaction. 334 effective_gas_price : 335 The price to charge for gas when the transaction is executed. 336 337 Raises 338 ------ 339 InvalidBlock : 340 If the transaction is not includable. 341 """ 342 ensure(tx.gas <= gas_available, InvalidBlock) 343 sender_address = recover_sender(chain_id, tx) 344 345 if isinstance(tx, FeeMarketTransaction): 346 ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock) 347 ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock) 348 349 priority_fee_per_gas = min( 350 tx.max_priority_fee_per_gas, 351 tx.max_fee_per_gas - base_fee_per_gas, 352 ) 353 effective_gas_price = priority_fee_per_gas + base_fee_per_gas 354 else: 355 ensure(tx.gas_price >= base_fee_per_gas, InvalidBlock) 356 effective_gas_price = tx.gas_price 357 358 return sender_address, effective_gas_price 359 360 361def make_receipt( 362 tx: Transaction, 363 error: Optional[Exception], 364 cumulative_gas_used: Uint, 365 logs: Tuple[Log, ...], 366) -> Union[Bytes, Receipt]: 367 """ 368 Make the receipt for a transaction that was executed. 369 370 Parameters 371 ---------- 372 tx : 373 The executed transaction. 374 error : 375 Error in the top level frame of the transaction, if any. 376 cumulative_gas_used : 377 The total gas used so far in the block after the transaction was 378 executed. 379 logs : 380 The logs produced by the transaction. 381 382 Returns 383 ------- 384 receipt : 385 The receipt for the transaction. 386 """ 387 receipt = Receipt( 388 succeeded=error is None, 389 cumulative_gas_used=cumulative_gas_used, 390 bloom=logs_bloom(logs), 391 logs=logs, 392 ) 393 394 if isinstance(tx, AccessListTransaction): 395 return b"\x01" + rlp.encode(receipt) 396 elif isinstance(tx, FeeMarketTransaction): 397 return b"\x02" + rlp.encode(receipt) 398 else: 399 return receipt 400 401 402def apply_body( 403 state: State, 404 block_hashes: List[Hash32], 405 coinbase: Address, 406 block_number: Uint, 407 base_fee_per_gas: Uint, 408 block_gas_limit: Uint, 409 block_time: U256, 410 prev_randao: Bytes32, 411 transactions: Tuple[Union[LegacyTransaction, Bytes], ...], 412 chain_id: U64, 413 withdrawals: Tuple[Withdrawal, ...], 414) -> Tuple[Uint, Root, Root, Bloom, State, Root]: 415 """ 416 Executes a block. 417 418 Many of the contents of a block are stored in data structures called 419 tries. There is a transactions trie which is similar to a ledger of the 420 transactions stored in the current block. There is also a receipts trie 421 which stores the results of executing a transaction, like the post state 422 and gas used. This function creates and executes the block that is to be 423 added to the chain. 424 425 Parameters 426 ---------- 427 state : 428 Current account state. 429 block_hashes : 430 List of hashes of the previous 256 blocks in the order of 431 increasing block number. 432 coinbase : 433 Address of account which receives block reward and transaction fees. 434 block_number : 435 Position of the block within the chain. 436 base_fee_per_gas : 437 Base fee per gas of within the block. 438 block_gas_limit : 439 Initial amount of gas available for execution in this block. 440 block_time : 441 Time the block was produced, measured in seconds since the epoch. 442 prev_randao : 443 The previous randao from the beacon chain. 444 transactions : 445 Transactions included in the block. 446 ommers : 447 Headers of ancestor blocks which are not direct parents (formerly 448 uncles.) 449 chain_id : 450 ID of the executing chain. 451 withdrawals : 452 Withdrawals to be processed in the current block. 453 454 Returns 455 ------- 456 block_gas_used : `ethereum.base_types.Uint` 457 Gas used for executing all transactions. 458 transactions_root : `ethereum.fork_types.Root` 459 Trie root of all the transactions in the block. 460 receipt_root : `ethereum.fork_types.Root` 461 Trie root of all the receipts in the block. 462 block_logs_bloom : `Bloom` 463 Logs bloom of all the logs included in all the transactions of the 464 block. 465 state : `ethereum.fork_types.State` 466 State after all transactions have been executed. 467 """ 468 gas_available = block_gas_limit 469 transactions_trie: Trie[ 470 Bytes, Optional[Union[Bytes, LegacyTransaction]] 471 ] = Trie(secured=False, default=None) 472 receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie( 473 secured=False, default=None 474 ) 475 withdrawals_trie: Trie[Bytes, Optional[Union[Bytes, Withdrawal]]] = Trie( 476 secured=False, default=None 477 ) 478 block_logs: Tuple[Log, ...] = () 479 480 for i, tx in enumerate(map(decode_transaction, transactions)): 481 trie_set( 482 transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx) 483 ) 484 485 sender_address, effective_gas_price = check_transaction( 486 tx, base_fee_per_gas, gas_available, chain_id 487 ) 488 489 env = vm.Environment( 490 caller=sender_address, 491 origin=sender_address, 492 block_hashes=block_hashes, 493 coinbase=coinbase, 494 number=block_number, 495 gas_limit=block_gas_limit, 496 base_fee_per_gas=base_fee_per_gas, 497 gas_price=effective_gas_price, 498 time=block_time, 499 prev_randao=prev_randao, 500 state=state, 501 chain_id=chain_id, 502 traces=[], 503 ) 504 505 gas_used, logs, error = process_transaction(env, tx) 506 gas_available -= gas_used 507 508 receipt = make_receipt( 509 tx, error, (block_gas_limit - gas_available), logs 510 ) 511 512 trie_set( 513 receipts_trie, 514 rlp.encode(Uint(i)), 515 receipt, 516 ) 517 518 block_logs += logs 519 520 block_gas_used = block_gas_limit - gas_available 521 522 block_logs_bloom = logs_bloom(block_logs) 523 524 for i, wd in enumerate(withdrawals): 525 trie_set(withdrawals_trie, rlp.encode(Uint(i)), rlp.encode(wd)) 526 527 process_withdrawal(state, wd) 528 529 if account_exists_and_is_empty(state, wd.address): 530 destroy_account(state, wd.address) 531 532 return ( 533 block_gas_used, 534 root(transactions_trie), 535 root(receipts_trie), 536 block_logs_bloom, 537 state, 538 root(withdrawals_trie), 539 ) 540 541 542def process_transaction( 543 env: vm.Environment, tx: Transaction 544) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: 545 """ 546 Execute a transaction against the provided environment. 547 548 This function processes the actions needed to execute a transaction. 549 It decrements the sender's account after calculating the gas fee and 550 refunds them the proper amount after execution. Calling contracts, 551 deploying code, and incrementing nonces are all examples of actions that 552 happen within this function or from a call made within this function. 553 554 Accounts that are marked for deletion are processed and destroyed after 555 execution. 556 557 Parameters 558 ---------- 559 env : 560 Environment for the Ethereum Virtual Machine. 561 tx : 562 Transaction to execute. 563 564 Returns 565 ------- 566 gas_left : `ethereum.base_types.U256` 567 Remaining gas after execution. 568 logs : `Tuple[ethereum.fork_types.Log, ...]` 569 Logs generated during execution. 570 """ 571 ensure(validate_transaction(tx), InvalidBlock) 572 573 sender = env.origin 574 sender_account = get_account(env.state, sender) 575 576 if isinstance(tx, FeeMarketTransaction): 577 max_gas_fee = tx.gas * tx.max_fee_per_gas 578 else: 579 max_gas_fee = tx.gas * tx.gas_price 580 581 ensure(sender_account.nonce == tx.nonce, InvalidBlock) 582 ensure(sender_account.balance >= max_gas_fee + tx.value, InvalidBlock) 583 ensure(sender_account.code == bytearray(), InvalidBlock) 584 585 effective_gas_fee = tx.gas * env.gas_price 586 587 gas = tx.gas - calculate_intrinsic_cost(tx) 588 increment_nonce(env.state, sender) 589 590 sender_balance_after_gas_fee = sender_account.balance - effective_gas_fee 591 set_account_balance(env.state, sender, sender_balance_after_gas_fee) 592 593 preaccessed_addresses = set() 594 preaccessed_storage_keys = set() 595 preaccessed_addresses.add(env.coinbase) 596 if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): 597 for address, keys in tx.access_list: 598 preaccessed_addresses.add(address) 599 for key in keys: 600 preaccessed_storage_keys.add((address, key)) 601 602 message = prepare_message( 603 sender, 604 tx.to, 605 tx.value, 606 tx.data, 607 gas, 608 env, 609 preaccessed_addresses=frozenset(preaccessed_addresses), 610 preaccessed_storage_keys=frozenset(preaccessed_storage_keys), 611 ) 612 613 output = process_message_call(message, env) 614 615 gas_used = tx.gas - output.gas_left 616 gas_refund = min(gas_used // 5, output.refund_counter) 617 gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price 618 619 # For non-1559 transactions env.gas_price == tx.gas_price 620 priority_fee_per_gas = env.gas_price - env.base_fee_per_gas 621 transaction_fee = ( 622 tx.gas - output.gas_left - gas_refund 623 ) * priority_fee_per_gas 624 625 total_gas_used = gas_used - gas_refund 626 627 # refund gas 628 sender_balance_after_refund = ( 629 get_account(env.state, sender).balance + gas_refund_amount 630 ) 631 set_account_balance(env.state, sender, sender_balance_after_refund) 632 633 # transfer miner fees 634 coinbase_balance_after_mining_fee = ( 635 get_account(env.state, env.coinbase).balance + transaction_fee 636 ) 637 if coinbase_balance_after_mining_fee != 0: 638 set_account_balance( 639 env.state, env.coinbase, coinbase_balance_after_mining_fee 640 ) 641 elif account_exists_and_is_empty(env.state, env.coinbase): 642 destroy_account(env.state, env.coinbase) 643 644 for address in output.accounts_to_delete: 645 destroy_account(env.state, address) 646 647 for address in output.touched_accounts: 648 if account_exists_and_is_empty(env.state, address): 649 destroy_account(env.state, address) 650 651 return total_gas_used, output.logs, output.error 652 653 654def validate_transaction(tx: Transaction) -> bool: 655 """ 656 Verifies a transaction. 657 658 The gas in a transaction gets used to pay for the intrinsic cost of 659 operations, therefore if there is insufficient gas then it would not 660 be possible to execute a transaction and it will be declared invalid. 661 662 Additionally, the nonce of a transaction must not equal or exceed the 663 limit defined in `EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>`_. 664 In practice, defining the limit as ``2**64-1`` has no impact because 665 sending ``2**64-1`` transactions is improbable. It's not strictly 666 impossible though, ``2**64-1`` transactions is the entire capacity of the 667 Ethereum blockchain at 2022 gas limits for a little over 22 years. 668 669 Parameters 670 ---------- 671 tx : 672 Transaction to validate. 673 674 Returns 675 ------- 676 verified : `bool` 677 True if the transaction can be executed, or False otherwise. 678 """ 679 if calculate_intrinsic_cost(tx) > tx.gas: 680 return False 681 if tx.nonce >= 2**64 - 1: 682 return False 683 if tx.to == Bytes0(b"") and len(tx.data) > 2 * MAX_CODE_SIZE: 684 return False 685 686 return True 687 688 689def calculate_intrinsic_cost(tx: Transaction) -> Uint: 690 """ 691 Calculates the gas that is charged before execution is started. 692 693 The intrinsic cost of the transaction is charged before execution has 694 begun. Functions/operations in the EVM cost money to execute so this 695 intrinsic cost is for the operations that need to be paid for as part of 696 the transaction. Data transfer, for example, is part of this intrinsic 697 cost. It costs ether to send data over the wire and that ether is 698 accounted for in the intrinsic cost calculated in this function. This 699 intrinsic cost must be calculated and paid for before execution in order 700 for all operations to be implemented. 701 702 Parameters 703 ---------- 704 tx : 705 Transaction to compute the intrinsic cost of. 706 707 Returns 708 ------- 709 verified : `ethereum.base_types.Uint` 710 The intrinsic cost of the transaction. 711 """ 712 data_cost = 0 713 714 for byte in tx.data: 715 if byte == 0: 716 data_cost += TX_DATA_COST_PER_ZERO 717 else: 718 data_cost += TX_DATA_COST_PER_NON_ZERO 719 720 if tx.to == Bytes0(b""): 721 create_cost = TX_CREATE_COST + int(init_code_cost(Uint(len(tx.data)))) 722 else: 723 create_cost = 0 724 725 access_list_cost = 0 726 if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): 727 for _address, keys in tx.access_list: 728 access_list_cost += TX_ACCESS_LIST_ADDRESS_COST 729 access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST 730 731 return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) 732 733 734def recover_sender(chain_id: U64, tx: Transaction) -> Address: 735 """ 736 Extracts the sender address from a transaction. 737 738 The v, r, and s values are the three parts that make up the signature 739 of a transaction. In order to recover the sender of a transaction the two 740 components needed are the signature (``v``, ``r``, and ``s``) and the 741 signing hash of the transaction. The sender's public key can be obtained 742 with these two values and therefore the sender address can be retrieved. 743 744 Parameters 745 ---------- 746 tx : 747 Transaction of interest. 748 chain_id : 749 ID of the executing chain. 750 751 Returns 752 ------- 753 sender : `ethereum.fork_types.Address` 754 The address of the account that signed the transaction. 755 """ 756 r, s = tx.r, tx.s 757 758 ensure(0 < r and r < SECP256K1N, InvalidBlock) 759 ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) 760 761 if isinstance(tx, LegacyTransaction): 762 v = tx.v 763 if v == 27 or v == 28: 764 public_key = secp256k1_recover( 765 r, s, v - 27, signing_hash_pre155(tx) 766 ) 767 else: 768 ensure( 769 v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock 770 ) 771 public_key = secp256k1_recover( 772 r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) 773 ) 774 elif isinstance(tx, AccessListTransaction): 775 public_key = secp256k1_recover( 776 r, s, tx.y_parity, signing_hash_2930(tx) 777 ) 778 elif isinstance(tx, FeeMarketTransaction): 779 public_key = secp256k1_recover( 780 r, s, tx.y_parity, signing_hash_1559(tx) 781 ) 782 783 return Address(keccak256(public_key)[12:32]) 784 785 786def signing_hash_pre155(tx: LegacyTransaction) -> Hash32: 787 """ 788 Compute the hash of a transaction used in a legacy (pre EIP 155) signature. 789 790 Parameters 791 ---------- 792 tx : 793 Transaction of interest. 794 795 Returns 796 ------- 797 hash : `ethereum.crypto.hash.Hash32` 798 Hash of the transaction. 799 """ 800 return keccak256( 801 rlp.encode( 802 ( 803 tx.nonce, 804 tx.gas_price, 805 tx.gas, 806 tx.to, 807 tx.value, 808 tx.data, 809 ) 810 ) 811 ) 812 813 814def signing_hash_155(tx: LegacyTransaction, chain_id: U64) -> Hash32: 815 """ 816 Compute the hash of a transaction used in a EIP 155 signature. 817 818 Parameters 819 ---------- 820 tx : 821 Transaction of interest. 822 chain_id : 823 The id of the current chain. 824 825 Returns 826 ------- 827 hash : `ethereum.crypto.hash.Hash32` 828 Hash of the transaction. 829 """ 830 return keccak256( 831 rlp.encode( 832 ( 833 tx.nonce, 834 tx.gas_price, 835 tx.gas, 836 tx.to, 837 tx.value, 838 tx.data, 839 chain_id, 840 Uint(0), 841 Uint(0), 842 ) 843 ) 844 ) 845 846 847def signing_hash_2930(tx: AccessListTransaction) -> Hash32: 848 """ 849 Compute the hash of a transaction used in a EIP 2930 signature. 850 851 Parameters 852 ---------- 853 tx : 854 Transaction of interest. 855 856 Returns 857 ------- 858 hash : `ethereum.crypto.hash.Hash32` 859 Hash of the transaction. 860 """ 861 return keccak256( 862 b"\x01" 863 + rlp.encode( 864 ( 865 tx.chain_id, 866 tx.nonce, 867 tx.gas_price, 868 tx.gas, 869 tx.to, 870 tx.value, 871 tx.data, 872 tx.access_list, 873 ) 874 ) 875 ) 876 877 878def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32: 879 """ 880 Compute the hash of a transaction used in a EIP 1559 signature. 881 882 Parameters 883 ---------- 884 tx : 885 Transaction of interest. 886 887 Returns 888 ------- 889 hash : `ethereum.crypto.hash.Hash32` 890 Hash of the transaction. 891 """ 892 return keccak256( 893 b"\x02" 894 + rlp.encode( 895 ( 896 tx.chain_id, 897 tx.nonce, 898 tx.max_priority_fee_per_gas, 899 tx.max_fee_per_gas, 900 tx.gas, 901 tx.to, 902 tx.value, 903 tx.data, 904 tx.access_list, 905 ) 906 ) 907 ) 908 909 910def compute_header_hash(header: Header) -> Hash32: 911 """ 912 Computes the hash of a block header. 913 914 The header hash of a block is the canonical hash that is used to refer 915 to a specific block and completely distinguishes a block from another. 916 917 ``keccak256`` is a function that produces a 256 bit hash of any input. 918 It also takes in any number of bytes as an input and produces a single 919 hash for them. A hash is a completely unique output for a single input. 920 So an input corresponds to one unique hash that can be used to identify 921 the input exactly. 922 923 Prior to using the ``keccak256`` hash function, the header must be 924 encoded using the Recursive-Length Prefix. See :ref:`rlp`. 925 RLP encoding the header converts it into a space-efficient format that 926 allows for easy transfer of data between nodes. The purpose of RLP is to 927 encode arbitrarily nested arrays of binary data, and RLP is the primary 928 encoding method used to serialize objects in Ethereum's execution layer. 929 The only purpose of RLP is to encode structure; encoding specific data 930 types (e.g. strings, floats) is left up to higher-order protocols. 931 932 Parameters 933 ---------- 934 header : 935 Header of interest. 936 937 Returns 938 ------- 939 hash : `ethereum.crypto.hash.Hash32` 940 Hash of the header. 941 """ 942 return keccak256(rlp.encode(header)) 943 944 945def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: 946 """ 947 Validates the gas limit for a block. 948 949 The bounds of the gas limit, ``max_adjustment_delta``, is set as the 950 quotient of the parent block's gas limit and the 951 ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is 952 passed through as a parameter is greater than or equal to the *sum* of 953 the parent's gas and the adjustment delta then the limit for gas is too 954 high and fails this function's check. Similarly, if the limit is less 955 than or equal to the *difference* of the parent's gas and the adjustment 956 delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's 957 check fails because the gas limit doesn't allow for a sufficient or 958 reasonable amount of gas to be used on a block. 959 960 Parameters 961 ---------- 962 gas_limit : 963 Gas limit to validate. 964 965 parent_gas_limit : 966 Gas limit of the parent block. 967 968 Returns 969 ------- 970 check : `bool` 971 True if gas limit constraints are satisfied, False otherwise. 972 """ 973 max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR 974 if gas_limit >= parent_gas_limit + max_adjustment_delta: 975 return False 976 if gas_limit <= parent_gas_limit - max_adjustment_delta: 977 return False 978 if gas_limit < GAS_LIMIT_MINIMUM: 979 return False 980 981 return True
73@dataclass 74class BlockChain: 75 """ 76 History and current state of the block chain. 77 """ 78 79 blocks: List[Block] 80 state: State 81 chain_id: U64
History and current state of the block chain.
84def apply_fork(old: BlockChain) -> BlockChain: 85 """ 86 Transforms the state from the previous hard fork (`old`) into the block 87 chain object for this hard fork and returns it. 88 89 When forks need to implement an irregular state transition, this function 90 is used to handle the irregularity. See the :ref:`DAO Fork <dao-fork>` for 91 an example. 92 93 Parameters 94 ---------- 95 old : 96 Previous block chain object. 97 98 Returns 99 ------- 100 new : `BlockChain` 101 Upgraded block chain object for this hard fork. 102 """ 103 return old
Transforms the state from the previous hard fork (old
) into the block
chain object for this hard fork and returns it.
When forks need to implement an irregular state transition, this function
is used to handle the irregularity. See the :ref:DAO Fork <dao-fork>
for
an example.
Parameters
old : Previous block chain object.
Returns
new : BlockChain
Upgraded block chain object for this hard fork.
106def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: 107 """ 108 Obtain the list of hashes of the previous 256 blocks in order of 109 increasing block number. 110 111 This function will return less hashes for the first 256 blocks. 112 113 The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, 114 therefore this function retrieves them. 115 116 Parameters 117 ---------- 118 chain : 119 History and current state. 120 121 Returns 122 ------- 123 recent_block_hashes : `List[Hash32]` 124 Hashes of the recent 256 blocks in order of increasing block number. 125 """ 126 recent_blocks = chain.blocks[-255:] 127 # TODO: This function has not been tested rigorously 128 if len(recent_blocks) == 0: 129 return [] 130 131 recent_block_hashes = [] 132 133 for block in recent_blocks: 134 prev_block_hash = block.header.parent_hash 135 recent_block_hashes.append(prev_block_hash) 136 137 # We are computing the hash only for the most recent block and not for 138 # the rest of the blocks as they have successors which have the hash of 139 # the current block as parent hash. 140 most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) 141 recent_block_hashes.append(most_recent_block_hash) 142 143 return recent_block_hashes
Obtain the list of hashes of the previous 256 blocks in order of increasing block number.
This function will return less hashes for the first 256 blocks.
The BLOCKHASH
opcode needs to access the latest hashes on the chain,
therefore this function retrieves them.
Parameters
chain : History and current state.
Returns
recent_block_hashes : List[Hash32]
Hashes of the recent 256 blocks in order of increasing block number.
146def state_transition(chain: BlockChain, block: Block) -> None: 147 """ 148 Attempts to apply a block to an existing block chain. 149 150 All parts of the block's contents need to be verified before being added 151 to the chain. Blocks are verified by ensuring that the contents of the 152 block make logical sense with the contents of the parent block. The 153 information in the block's header must also match the corresponding 154 information in the block. 155 156 To implement Ethereum, in theory clients are only required to store the 157 most recent 255 blocks of the chain since as far as execution is 158 concerned, only those blocks are accessed. Practically, however, clients 159 should store more blocks to handle reorgs. 160 161 Parameters 162 ---------- 163 chain : 164 History and current state. 165 block : 166 Block to apply to `chain`. 167 """ 168 parent_header = chain.blocks[-1].header 169 validate_header(block.header, parent_header) 170 ensure(block.ommers == (), InvalidBlock) 171 ( 172 gas_used, 173 transactions_root, 174 receipt_root, 175 block_logs_bloom, 176 state, 177 withdrawals_root, 178 ) = apply_body( 179 chain.state, 180 get_last_256_block_hashes(chain), 181 block.header.coinbase, 182 block.header.number, 183 block.header.base_fee_per_gas, 184 block.header.gas_limit, 185 block.header.timestamp, 186 block.header.prev_randao, 187 block.transactions, 188 chain.chain_id, 189 block.withdrawals, 190 ) 191 ensure(gas_used == block.header.gas_used, InvalidBlock) 192 ensure(transactions_root == block.header.transactions_root, InvalidBlock) 193 ensure(state_root(state) == block.header.state_root, InvalidBlock) 194 ensure(receipt_root == block.header.receipt_root, InvalidBlock) 195 ensure(block_logs_bloom == block.header.bloom, InvalidBlock) 196 ensure(withdrawals_root == block.header.withdrawals_root, InvalidBlock) 197 198 chain.blocks.append(block) 199 if len(chain.blocks) > 255: 200 # Real clients have to store more blocks to deal with reorgs, but the 201 # protocol only requires the last 255 202 chain.blocks = chain.blocks[-255:]
Attempts to apply a block to an existing block chain.
All parts of the block's contents need to be verified before being added to the chain. Blocks are verified by ensuring that the contents of the block make logical sense with the contents of the parent block. The information in the block's header must also match the corresponding information in the block.
To implement Ethereum, in theory clients are only required to store the most recent 255 blocks of the chain since as far as execution is concerned, only those blocks are accessed. Practically, however, clients should store more blocks to handle reorgs.
Parameters
chain :
History and current state.
block :
Block to apply to chain
.
205def calculate_base_fee_per_gas( 206 block_gas_limit: Uint, 207 parent_gas_limit: Uint, 208 parent_gas_used: Uint, 209 parent_base_fee_per_gas: Uint, 210) -> Uint: 211 """ 212 Calculates the base fee per gas for the block. 213 214 Parameters 215 ---------- 216 block_gas_limit : 217 Gas limit of the block for which the base fee is being calculated. 218 parent_gas_limit : 219 Gas limit of the parent block. 220 parent_gas_used : 221 Gas used in the parent block. 222 parent_base_fee_per_gas : 223 Base fee per gas of the parent block. 224 225 Returns 226 ------- 227 base_fee_per_gas : `Uint` 228 Base fee per gas for the block. 229 """ 230 parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER 231 232 ensure( 233 check_gas_limit(block_gas_limit, parent_gas_limit), 234 InvalidBlock, 235 ) 236 237 if parent_gas_used == parent_gas_target: 238 expected_base_fee_per_gas = parent_base_fee_per_gas 239 elif parent_gas_used > parent_gas_target: 240 gas_used_delta = parent_gas_used - parent_gas_target 241 242 parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta 243 target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target 244 245 base_fee_per_gas_delta = max( 246 target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR, 247 1, 248 ) 249 250 expected_base_fee_per_gas = ( 251 parent_base_fee_per_gas + base_fee_per_gas_delta 252 ) 253 else: 254 gas_used_delta = parent_gas_target - parent_gas_used 255 256 parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta 257 target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target 258 259 base_fee_per_gas_delta = ( 260 target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR 261 ) 262 263 expected_base_fee_per_gas = ( 264 parent_base_fee_per_gas - base_fee_per_gas_delta 265 ) 266 267 return Uint(expected_base_fee_per_gas)
Calculates the base fee per gas for the block.
Parameters
block_gas_limit : Gas limit of the block for which the base fee is being calculated. parent_gas_limit : Gas limit of the parent block. parent_gas_used : Gas used in the parent block. parent_base_fee_per_gas : Base fee per gas of the parent block.
Returns
base_fee_per_gas : Uint
Base fee per gas for the block.
270def validate_header(header: Header, parent_header: Header) -> None: 271 """ 272 Verifies a block header. 273 274 In order to consider a block's header valid, the logic for the 275 quantities in the header should match the logic for the block itself. 276 For example the header timestamp should be greater than the block's parent 277 timestamp because the block was created *after* the parent block. 278 Additionally, the block's number should be directly following the parent 279 block's number since it is the next block in the sequence. 280 281 Parameters 282 ---------- 283 header : 284 Header to check for correctness. 285 parent_header : 286 Parent Header of the header to check for correctness 287 """ 288 ensure(header.gas_used <= header.gas_limit, InvalidBlock) 289 290 expected_base_fee_per_gas = calculate_base_fee_per_gas( 291 header.gas_limit, 292 parent_header.gas_limit, 293 parent_header.gas_used, 294 parent_header.base_fee_per_gas, 295 ) 296 297 ensure(expected_base_fee_per_gas == header.base_fee_per_gas, InvalidBlock) 298 299 ensure(header.timestamp > parent_header.timestamp, InvalidBlock) 300 ensure(header.number == parent_header.number + 1, InvalidBlock) 301 ensure(len(header.extra_data) <= 32, InvalidBlock) 302 303 ensure(header.difficulty == 0, InvalidBlock) 304 ensure(header.nonce == b"\x00\x00\x00\x00\x00\x00\x00\x00", InvalidBlock) 305 ensure(header.ommers_hash == EMPTY_OMMER_HASH, InvalidBlock) 306 307 block_parent_hash = keccak256(rlp.encode(parent_header)) 308 ensure(header.parent_hash == block_parent_hash, InvalidBlock)
Verifies a block header.
In order to consider a block's header valid, the logic for the quantities in the header should match the logic for the block itself. For example the header timestamp should be greater than the block's parent timestamp because the block was created after the parent block. Additionally, the block's number should be directly following the parent block's number since it is the next block in the sequence.
Parameters
header : Header to check for correctness. parent_header : Parent Header of the header to check for correctness
311def check_transaction( 312 tx: Transaction, 313 base_fee_per_gas: Uint, 314 gas_available: Uint, 315 chain_id: U64, 316) -> Tuple[Address, Uint]: 317 """ 318 Check if the transaction is includable in the block. 319 320 Parameters 321 ---------- 322 tx : 323 The transaction. 324 base_fee_per_gas : 325 The block base fee. 326 gas_available : 327 The gas remaining in the block. 328 chain_id : 329 The ID of the current chain. 330 331 Returns 332 ------- 333 sender_address : 334 The sender of the transaction. 335 effective_gas_price : 336 The price to charge for gas when the transaction is executed. 337 338 Raises 339 ------ 340 InvalidBlock : 341 If the transaction is not includable. 342 """ 343 ensure(tx.gas <= gas_available, InvalidBlock) 344 sender_address = recover_sender(chain_id, tx) 345 346 if isinstance(tx, FeeMarketTransaction): 347 ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock) 348 ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock) 349 350 priority_fee_per_gas = min( 351 tx.max_priority_fee_per_gas, 352 tx.max_fee_per_gas - base_fee_per_gas, 353 ) 354 effective_gas_price = priority_fee_per_gas + base_fee_per_gas 355 else: 356 ensure(tx.gas_price >= base_fee_per_gas, InvalidBlock) 357 effective_gas_price = tx.gas_price 358 359 return sender_address, effective_gas_price
Check if the transaction is includable in the block.
Parameters
tx : The transaction. base_fee_per_gas : The block base fee. gas_available : The gas remaining in the block. chain_id : The ID of the current chain.
Returns
sender_address : The sender of the transaction. effective_gas_price : The price to charge for gas when the transaction is executed.
Raises
InvalidBlock : If the transaction is not includable.
362def make_receipt( 363 tx: Transaction, 364 error: Optional[Exception], 365 cumulative_gas_used: Uint, 366 logs: Tuple[Log, ...], 367) -> Union[Bytes, Receipt]: 368 """ 369 Make the receipt for a transaction that was executed. 370 371 Parameters 372 ---------- 373 tx : 374 The executed transaction. 375 error : 376 Error in the top level frame of the transaction, if any. 377 cumulative_gas_used : 378 The total gas used so far in the block after the transaction was 379 executed. 380 logs : 381 The logs produced by the transaction. 382 383 Returns 384 ------- 385 receipt : 386 The receipt for the transaction. 387 """ 388 receipt = Receipt( 389 succeeded=error is None, 390 cumulative_gas_used=cumulative_gas_used, 391 bloom=logs_bloom(logs), 392 logs=logs, 393 ) 394 395 if isinstance(tx, AccessListTransaction): 396 return b"\x01" + rlp.encode(receipt) 397 elif isinstance(tx, FeeMarketTransaction): 398 return b"\x02" + rlp.encode(receipt) 399 else: 400 return receipt
Make the receipt for a transaction that was executed.
Parameters
tx : The executed transaction. error : Error in the top level frame of the transaction, if any. cumulative_gas_used : The total gas used so far in the block after the transaction was executed. logs : The logs produced by the transaction.
Returns
receipt : The receipt for the transaction.
403def apply_body( 404 state: State, 405 block_hashes: List[Hash32], 406 coinbase: Address, 407 block_number: Uint, 408 base_fee_per_gas: Uint, 409 block_gas_limit: Uint, 410 block_time: U256, 411 prev_randao: Bytes32, 412 transactions: Tuple[Union[LegacyTransaction, Bytes], ...], 413 chain_id: U64, 414 withdrawals: Tuple[Withdrawal, ...], 415) -> Tuple[Uint, Root, Root, Bloom, State, Root]: 416 """ 417 Executes a block. 418 419 Many of the contents of a block are stored in data structures called 420 tries. There is a transactions trie which is similar to a ledger of the 421 transactions stored in the current block. There is also a receipts trie 422 which stores the results of executing a transaction, like the post state 423 and gas used. This function creates and executes the block that is to be 424 added to the chain. 425 426 Parameters 427 ---------- 428 state : 429 Current account state. 430 block_hashes : 431 List of hashes of the previous 256 blocks in the order of 432 increasing block number. 433 coinbase : 434 Address of account which receives block reward and transaction fees. 435 block_number : 436 Position of the block within the chain. 437 base_fee_per_gas : 438 Base fee per gas of within the block. 439 block_gas_limit : 440 Initial amount of gas available for execution in this block. 441 block_time : 442 Time the block was produced, measured in seconds since the epoch. 443 prev_randao : 444 The previous randao from the beacon chain. 445 transactions : 446 Transactions included in the block. 447 ommers : 448 Headers of ancestor blocks which are not direct parents (formerly 449 uncles.) 450 chain_id : 451 ID of the executing chain. 452 withdrawals : 453 Withdrawals to be processed in the current block. 454 455 Returns 456 ------- 457 block_gas_used : `ethereum.base_types.Uint` 458 Gas used for executing all transactions. 459 transactions_root : `ethereum.fork_types.Root` 460 Trie root of all the transactions in the block. 461 receipt_root : `ethereum.fork_types.Root` 462 Trie root of all the receipts in the block. 463 block_logs_bloom : `Bloom` 464 Logs bloom of all the logs included in all the transactions of the 465 block. 466 state : `ethereum.fork_types.State` 467 State after all transactions have been executed. 468 """ 469 gas_available = block_gas_limit 470 transactions_trie: Trie[ 471 Bytes, Optional[Union[Bytes, LegacyTransaction]] 472 ] = Trie(secured=False, default=None) 473 receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie( 474 secured=False, default=None 475 ) 476 withdrawals_trie: Trie[Bytes, Optional[Union[Bytes, Withdrawal]]] = Trie( 477 secured=False, default=None 478 ) 479 block_logs: Tuple[Log, ...] = () 480 481 for i, tx in enumerate(map(decode_transaction, transactions)): 482 trie_set( 483 transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx) 484 ) 485 486 sender_address, effective_gas_price = check_transaction( 487 tx, base_fee_per_gas, gas_available, chain_id 488 ) 489 490 env = vm.Environment( 491 caller=sender_address, 492 origin=sender_address, 493 block_hashes=block_hashes, 494 coinbase=coinbase, 495 number=block_number, 496 gas_limit=block_gas_limit, 497 base_fee_per_gas=base_fee_per_gas, 498 gas_price=effective_gas_price, 499 time=block_time, 500 prev_randao=prev_randao, 501 state=state, 502 chain_id=chain_id, 503 traces=[], 504 ) 505 506 gas_used, logs, error = process_transaction(env, tx) 507 gas_available -= gas_used 508 509 receipt = make_receipt( 510 tx, error, (block_gas_limit - gas_available), logs 511 ) 512 513 trie_set( 514 receipts_trie, 515 rlp.encode(Uint(i)), 516 receipt, 517 ) 518 519 block_logs += logs 520 521 block_gas_used = block_gas_limit - gas_available 522 523 block_logs_bloom = logs_bloom(block_logs) 524 525 for i, wd in enumerate(withdrawals): 526 trie_set(withdrawals_trie, rlp.encode(Uint(i)), rlp.encode(wd)) 527 528 process_withdrawal(state, wd) 529 530 if account_exists_and_is_empty(state, wd.address): 531 destroy_account(state, wd.address) 532 533 return ( 534 block_gas_used, 535 root(transactions_trie), 536 root(receipts_trie), 537 block_logs_bloom, 538 state, 539 root(withdrawals_trie), 540 )
Executes a block.
Many of the contents of a block are stored in data structures called tries. There is a transactions trie which is similar to a ledger of the transactions stored in the current block. There is also a receipts trie which stores the results of executing a transaction, like the post state and gas used. This function creates and executes the block that is to be added to the chain.
Parameters
state : Current account state. block_hashes : List of hashes of the previous 256 blocks in the order of increasing block number. coinbase : Address of account which receives block reward and transaction fees. block_number : Position of the block within the chain. base_fee_per_gas : Base fee per gas of within the block. block_gas_limit : Initial amount of gas available for execution in this block. block_time : Time the block was produced, measured in seconds since the epoch. prev_randao : The previous randao from the beacon chain. transactions : Transactions included in the block. ommers : Headers of ancestor blocks which are not direct parents (formerly uncles.) chain_id : ID of the executing chain. withdrawals : Withdrawals to be processed in the current block.
Returns
block_gas_used : ethereum.base_types.Uint
Gas used for executing all transactions.
transactions_root : ethereum.fork_types.Root
Trie root of all the transactions in the block.
receipt_root : ethereum.fork_types.Root
Trie root of all the receipts in the block.
block_logs_bloom : Bloom
Logs bloom of all the logs included in all the transactions of the
block.
state : ethereum.fork_types.State
State after all transactions have been executed.
543def process_transaction( 544 env: vm.Environment, tx: Transaction 545) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: 546 """ 547 Execute a transaction against the provided environment. 548 549 This function processes the actions needed to execute a transaction. 550 It decrements the sender's account after calculating the gas fee and 551 refunds them the proper amount after execution. Calling contracts, 552 deploying code, and incrementing nonces are all examples of actions that 553 happen within this function or from a call made within this function. 554 555 Accounts that are marked for deletion are processed and destroyed after 556 execution. 557 558 Parameters 559 ---------- 560 env : 561 Environment for the Ethereum Virtual Machine. 562 tx : 563 Transaction to execute. 564 565 Returns 566 ------- 567 gas_left : `ethereum.base_types.U256` 568 Remaining gas after execution. 569 logs : `Tuple[ethereum.fork_types.Log, ...]` 570 Logs generated during execution. 571 """ 572 ensure(validate_transaction(tx), InvalidBlock) 573 574 sender = env.origin 575 sender_account = get_account(env.state, sender) 576 577 if isinstance(tx, FeeMarketTransaction): 578 max_gas_fee = tx.gas * tx.max_fee_per_gas 579 else: 580 max_gas_fee = tx.gas * tx.gas_price 581 582 ensure(sender_account.nonce == tx.nonce, InvalidBlock) 583 ensure(sender_account.balance >= max_gas_fee + tx.value, InvalidBlock) 584 ensure(sender_account.code == bytearray(), InvalidBlock) 585 586 effective_gas_fee = tx.gas * env.gas_price 587 588 gas = tx.gas - calculate_intrinsic_cost(tx) 589 increment_nonce(env.state, sender) 590 591 sender_balance_after_gas_fee = sender_account.balance - effective_gas_fee 592 set_account_balance(env.state, sender, sender_balance_after_gas_fee) 593 594 preaccessed_addresses = set() 595 preaccessed_storage_keys = set() 596 preaccessed_addresses.add(env.coinbase) 597 if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): 598 for address, keys in tx.access_list: 599 preaccessed_addresses.add(address) 600 for key in keys: 601 preaccessed_storage_keys.add((address, key)) 602 603 message = prepare_message( 604 sender, 605 tx.to, 606 tx.value, 607 tx.data, 608 gas, 609 env, 610 preaccessed_addresses=frozenset(preaccessed_addresses), 611 preaccessed_storage_keys=frozenset(preaccessed_storage_keys), 612 ) 613 614 output = process_message_call(message, env) 615 616 gas_used = tx.gas - output.gas_left 617 gas_refund = min(gas_used // 5, output.refund_counter) 618 gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price 619 620 # For non-1559 transactions env.gas_price == tx.gas_price 621 priority_fee_per_gas = env.gas_price - env.base_fee_per_gas 622 transaction_fee = ( 623 tx.gas - output.gas_left - gas_refund 624 ) * priority_fee_per_gas 625 626 total_gas_used = gas_used - gas_refund 627 628 # refund gas 629 sender_balance_after_refund = ( 630 get_account(env.state, sender).balance + gas_refund_amount 631 ) 632 set_account_balance(env.state, sender, sender_balance_after_refund) 633 634 # transfer miner fees 635 coinbase_balance_after_mining_fee = ( 636 get_account(env.state, env.coinbase).balance + transaction_fee 637 ) 638 if coinbase_balance_after_mining_fee != 0: 639 set_account_balance( 640 env.state, env.coinbase, coinbase_balance_after_mining_fee 641 ) 642 elif account_exists_and_is_empty(env.state, env.coinbase): 643 destroy_account(env.state, env.coinbase) 644 645 for address in output.accounts_to_delete: 646 destroy_account(env.state, address) 647 648 for address in output.touched_accounts: 649 if account_exists_and_is_empty(env.state, address): 650 destroy_account(env.state, address) 651 652 return total_gas_used, output.logs, output.error
Execute a transaction against the provided environment.
This function processes the actions needed to execute a transaction. It decrements the sender's account after calculating the gas fee and refunds them the proper amount after execution. Calling contracts, deploying code, and incrementing nonces are all examples of actions that happen within this function or from a call made within this function.
Accounts that are marked for deletion are processed and destroyed after execution.
Parameters
env : Environment for the Ethereum Virtual Machine. tx : Transaction to execute.
Returns
gas_left : ethereum.base_types.U256
Remaining gas after execution.
logs : Tuple[ethereum.fork_types.Log, ...]
Logs generated during execution.
655def validate_transaction(tx: Transaction) -> bool: 656 """ 657 Verifies a transaction. 658 659 The gas in a transaction gets used to pay for the intrinsic cost of 660 operations, therefore if there is insufficient gas then it would not 661 be possible to execute a transaction and it will be declared invalid. 662 663 Additionally, the nonce of a transaction must not equal or exceed the 664 limit defined in `EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>`_. 665 In practice, defining the limit as ``2**64-1`` has no impact because 666 sending ``2**64-1`` transactions is improbable. It's not strictly 667 impossible though, ``2**64-1`` transactions is the entire capacity of the 668 Ethereum blockchain at 2022 gas limits for a little over 22 years. 669 670 Parameters 671 ---------- 672 tx : 673 Transaction to validate. 674 675 Returns 676 ------- 677 verified : `bool` 678 True if the transaction can be executed, or False otherwise. 679 """ 680 if calculate_intrinsic_cost(tx) > tx.gas: 681 return False 682 if tx.nonce >= 2**64 - 1: 683 return False 684 if tx.to == Bytes0(b"") and len(tx.data) > 2 * MAX_CODE_SIZE: 685 return False 686 687 return True
Verifies a transaction.
The gas in a transaction gets used to pay for the intrinsic cost of operations, therefore if there is insufficient gas then it would not be possible to execute a transaction and it will be declared invalid.
Additionally, the nonce of a transaction must not equal or exceed the
limit defined in EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>
_.
In practice, defining the limit as 2**64-1
has no impact because
sending 2**64-1
transactions is improbable. It's not strictly
impossible though, 2**64-1
transactions is the entire capacity of the
Ethereum blockchain at 2022 gas limits for a little over 22 years.
Parameters
tx : Transaction to validate.
Returns
verified : bool
True if the transaction can be executed, or False otherwise.
690def calculate_intrinsic_cost(tx: Transaction) -> Uint: 691 """ 692 Calculates the gas that is charged before execution is started. 693 694 The intrinsic cost of the transaction is charged before execution has 695 begun. Functions/operations in the EVM cost money to execute so this 696 intrinsic cost is for the operations that need to be paid for as part of 697 the transaction. Data transfer, for example, is part of this intrinsic 698 cost. It costs ether to send data over the wire and that ether is 699 accounted for in the intrinsic cost calculated in this function. This 700 intrinsic cost must be calculated and paid for before execution in order 701 for all operations to be implemented. 702 703 Parameters 704 ---------- 705 tx : 706 Transaction to compute the intrinsic cost of. 707 708 Returns 709 ------- 710 verified : `ethereum.base_types.Uint` 711 The intrinsic cost of the transaction. 712 """ 713 data_cost = 0 714 715 for byte in tx.data: 716 if byte == 0: 717 data_cost += TX_DATA_COST_PER_ZERO 718 else: 719 data_cost += TX_DATA_COST_PER_NON_ZERO 720 721 if tx.to == Bytes0(b""): 722 create_cost = TX_CREATE_COST + int(init_code_cost(Uint(len(tx.data)))) 723 else: 724 create_cost = 0 725 726 access_list_cost = 0 727 if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): 728 for _address, keys in tx.access_list: 729 access_list_cost += TX_ACCESS_LIST_ADDRESS_COST 730 access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST 731 732 return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost)
Calculates the gas that is charged before execution is started.
The intrinsic cost of the transaction is charged before execution has begun. Functions/operations in the EVM cost money to execute so this intrinsic cost is for the operations that need to be paid for as part of the transaction. Data transfer, for example, is part of this intrinsic cost. It costs ether to send data over the wire and that ether is accounted for in the intrinsic cost calculated in this function. This intrinsic cost must be calculated and paid for before execution in order for all operations to be implemented.
Parameters
tx : Transaction to compute the intrinsic cost of.
Returns
verified : ethereum.base_types.Uint
The intrinsic cost of the transaction.
735def recover_sender(chain_id: U64, tx: Transaction) -> Address: 736 """ 737 Extracts the sender address from a transaction. 738 739 The v, r, and s values are the three parts that make up the signature 740 of a transaction. In order to recover the sender of a transaction the two 741 components needed are the signature (``v``, ``r``, and ``s``) and the 742 signing hash of the transaction. The sender's public key can be obtained 743 with these two values and therefore the sender address can be retrieved. 744 745 Parameters 746 ---------- 747 tx : 748 Transaction of interest. 749 chain_id : 750 ID of the executing chain. 751 752 Returns 753 ------- 754 sender : `ethereum.fork_types.Address` 755 The address of the account that signed the transaction. 756 """ 757 r, s = tx.r, tx.s 758 759 ensure(0 < r and r < SECP256K1N, InvalidBlock) 760 ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) 761 762 if isinstance(tx, LegacyTransaction): 763 v = tx.v 764 if v == 27 or v == 28: 765 public_key = secp256k1_recover( 766 r, s, v - 27, signing_hash_pre155(tx) 767 ) 768 else: 769 ensure( 770 v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock 771 ) 772 public_key = secp256k1_recover( 773 r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) 774 ) 775 elif isinstance(tx, AccessListTransaction): 776 public_key = secp256k1_recover( 777 r, s, tx.y_parity, signing_hash_2930(tx) 778 ) 779 elif isinstance(tx, FeeMarketTransaction): 780 public_key = secp256k1_recover( 781 r, s, tx.y_parity, signing_hash_1559(tx) 782 ) 783 784 return Address(keccak256(public_key)[12:32])
Extracts the sender address from a transaction.
The v, r, and s values are the three parts that make up the signature
of a transaction. In order to recover the sender of a transaction the two
components needed are the signature (v
, r
, and s
) and the
signing hash of the transaction. The sender's public key can be obtained
with these two values and therefore the sender address can be retrieved.
Parameters
tx : Transaction of interest. chain_id : ID of the executing chain.
Returns
sender : ethereum.fork_types.Address
The address of the account that signed the transaction.
787def signing_hash_pre155(tx: LegacyTransaction) -> Hash32: 788 """ 789 Compute the hash of a transaction used in a legacy (pre EIP 155) signature. 790 791 Parameters 792 ---------- 793 tx : 794 Transaction of interest. 795 796 Returns 797 ------- 798 hash : `ethereum.crypto.hash.Hash32` 799 Hash of the transaction. 800 """ 801 return keccak256( 802 rlp.encode( 803 ( 804 tx.nonce, 805 tx.gas_price, 806 tx.gas, 807 tx.to, 808 tx.value, 809 tx.data, 810 ) 811 ) 812 )
Compute the hash of a transaction used in a legacy (pre EIP 155) signature.
Parameters
tx : Transaction of interest.
Returns
hash : ethereum.crypto.hash.Hash32
Hash of the transaction.
815def signing_hash_155(tx: LegacyTransaction, chain_id: U64) -> Hash32: 816 """ 817 Compute the hash of a transaction used in a EIP 155 signature. 818 819 Parameters 820 ---------- 821 tx : 822 Transaction of interest. 823 chain_id : 824 The id of the current chain. 825 826 Returns 827 ------- 828 hash : `ethereum.crypto.hash.Hash32` 829 Hash of the transaction. 830 """ 831 return keccak256( 832 rlp.encode( 833 ( 834 tx.nonce, 835 tx.gas_price, 836 tx.gas, 837 tx.to, 838 tx.value, 839 tx.data, 840 chain_id, 841 Uint(0), 842 Uint(0), 843 ) 844 ) 845 )
Compute the hash of a transaction used in a EIP 155 signature.
Parameters
tx : Transaction of interest. chain_id : The id of the current chain.
Returns
hash : ethereum.crypto.hash.Hash32
Hash of the transaction.
848def signing_hash_2930(tx: AccessListTransaction) -> Hash32: 849 """ 850 Compute the hash of a transaction used in a EIP 2930 signature. 851 852 Parameters 853 ---------- 854 tx : 855 Transaction of interest. 856 857 Returns 858 ------- 859 hash : `ethereum.crypto.hash.Hash32` 860 Hash of the transaction. 861 """ 862 return keccak256( 863 b"\x01" 864 + rlp.encode( 865 ( 866 tx.chain_id, 867 tx.nonce, 868 tx.gas_price, 869 tx.gas, 870 tx.to, 871 tx.value, 872 tx.data, 873 tx.access_list, 874 ) 875 ) 876 )
Compute the hash of a transaction used in a EIP 2930 signature.
Parameters
tx : Transaction of interest.
Returns
hash : ethereum.crypto.hash.Hash32
Hash of the transaction.
879def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32: 880 """ 881 Compute the hash of a transaction used in a EIP 1559 signature. 882 883 Parameters 884 ---------- 885 tx : 886 Transaction of interest. 887 888 Returns 889 ------- 890 hash : `ethereum.crypto.hash.Hash32` 891 Hash of the transaction. 892 """ 893 return keccak256( 894 b"\x02" 895 + rlp.encode( 896 ( 897 tx.chain_id, 898 tx.nonce, 899 tx.max_priority_fee_per_gas, 900 tx.max_fee_per_gas, 901 tx.gas, 902 tx.to, 903 tx.value, 904 tx.data, 905 tx.access_list, 906 ) 907 ) 908 )
Compute the hash of a transaction used in a EIP 1559 signature.
Parameters
tx : Transaction of interest.
Returns
hash : ethereum.crypto.hash.Hash32
Hash of the transaction.
911def compute_header_hash(header: Header) -> Hash32: 912 """ 913 Computes the hash of a block header. 914 915 The header hash of a block is the canonical hash that is used to refer 916 to a specific block and completely distinguishes a block from another. 917 918 ``keccak256`` is a function that produces a 256 bit hash of any input. 919 It also takes in any number of bytes as an input and produces a single 920 hash for them. A hash is a completely unique output for a single input. 921 So an input corresponds to one unique hash that can be used to identify 922 the input exactly. 923 924 Prior to using the ``keccak256`` hash function, the header must be 925 encoded using the Recursive-Length Prefix. See :ref:`rlp`. 926 RLP encoding the header converts it into a space-efficient format that 927 allows for easy transfer of data between nodes. The purpose of RLP is to 928 encode arbitrarily nested arrays of binary data, and RLP is the primary 929 encoding method used to serialize objects in Ethereum's execution layer. 930 The only purpose of RLP is to encode structure; encoding specific data 931 types (e.g. strings, floats) is left up to higher-order protocols. 932 933 Parameters 934 ---------- 935 header : 936 Header of interest. 937 938 Returns 939 ------- 940 hash : `ethereum.crypto.hash.Hash32` 941 Hash of the header. 942 """ 943 return keccak256(rlp.encode(header))
Computes the hash of a block header.
The header hash of a block is the canonical hash that is used to refer to a specific block and completely distinguishes a block from another.
keccak256
is a function that produces a 256 bit hash of any input.
It also takes in any number of bytes as an input and produces a single
hash for them. A hash is a completely unique output for a single input.
So an input corresponds to one unique hash that can be used to identify
the input exactly.
Prior to using the keccak256
hash function, the header must be
encoded using the Recursive-Length Prefix. See :ref:rlp
.
RLP encoding the header converts it into a space-efficient format that
allows for easy transfer of data between nodes. The purpose of RLP is to
encode arbitrarily nested arrays of binary data, and RLP is the primary
encoding method used to serialize objects in Ethereum's execution layer.
The only purpose of RLP is to encode structure; encoding specific data
types (e.g. strings, floats) is left up to higher-order protocols.
Parameters
header : Header of interest.
Returns
hash : ethereum.crypto.hash.Hash32
Hash of the header.
946def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: 947 """ 948 Validates the gas limit for a block. 949 950 The bounds of the gas limit, ``max_adjustment_delta``, is set as the 951 quotient of the parent block's gas limit and the 952 ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is 953 passed through as a parameter is greater than or equal to the *sum* of 954 the parent's gas and the adjustment delta then the limit for gas is too 955 high and fails this function's check. Similarly, if the limit is less 956 than or equal to the *difference* of the parent's gas and the adjustment 957 delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's 958 check fails because the gas limit doesn't allow for a sufficient or 959 reasonable amount of gas to be used on a block. 960 961 Parameters 962 ---------- 963 gas_limit : 964 Gas limit to validate. 965 966 parent_gas_limit : 967 Gas limit of the parent block. 968 969 Returns 970 ------- 971 check : `bool` 972 True if gas limit constraints are satisfied, False otherwise. 973 """ 974 max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR 975 if gas_limit >= parent_gas_limit + max_adjustment_delta: 976 return False 977 if gas_limit <= parent_gas_limit - max_adjustment_delta: 978 return False 979 if gas_limit < GAS_LIMIT_MINIMUM: 980 return False 981 982 return True
Validates the gas limit for a block.
The bounds of the gas limit, max_adjustment_delta
, is set as the
quotient of the parent block's gas limit and the
GAS_LIMIT_ADJUSTMENT_FACTOR
. Therefore, if the gas limit that is
passed through as a parameter is greater than or equal to the sum of
the parent's gas and the adjustment delta then the limit for gas is too
high and fails this function's check. Similarly, if the limit is less
than or equal to the difference of the parent's gas and the adjustment
delta or the predefined GAS_LIMIT_MINIMUM
then this function's
check fails because the gas limit doesn't allow for a sufficient or
reasonable amount of gas to be used on a block.
Parameters
gas_limit : Gas limit to validate.
parent_gas_limit : Gas limit of the parent block.
Returns
check : bool
True if gas limit constraints are satisfied, False otherwise.