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