ethereum.london.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, Set, Tuple, Union 17 18from ethereum.base_types import Bytes0 19from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover 20from ethereum.crypto.hash import Hash32, keccak256 21from ethereum.ethash import dataset_size, generate_cache, hashimoto_light 22from ethereum.exceptions import InvalidBlock 23from ethereum.utils.ensure import ensure 24 25from .. import rlp 26from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Uint 27from . import FORK_CRITERIA, vm 28from .bloom import logs_bloom 29from .fork_types import ( 30 TX_ACCESS_LIST_ADDRESS_COST, 31 TX_ACCESS_LIST_STORAGE_KEY_COST, 32 TX_BASE_COST, 33 TX_CREATE_COST, 34 TX_DATA_COST_PER_NON_ZERO, 35 TX_DATA_COST_PER_ZERO, 36 AccessListTransaction, 37 Address, 38 Block, 39 Bloom, 40 FeeMarketTransaction, 41 Header, 42 LegacyTransaction, 43 Log, 44 Receipt, 45 Root, 46 Transaction, 47 decode_transaction, 48 encode_transaction, 49) 50from .state import ( 51 State, 52 account_exists_and_is_empty, 53 create_ether, 54 destroy_account, 55 get_account, 56 increment_nonce, 57 set_account_balance, 58 state_root, 59) 60from .trie import Trie, root, trie_set 61from .utils.message import prepare_message 62from .vm.interpreter import process_message_call 63 64BLOCK_REWARD = U256(2 * 10**18) 65BASE_FEE_MAX_CHANGE_DENOMINATOR = 8 66ELASTICITY_MULTIPLIER = 2 67GAS_LIMIT_ADJUSTMENT_FACTOR = 1024 68GAS_LIMIT_MINIMUM = 5000 69MINIMUM_DIFFICULTY = Uint(131072) 70INITIAL_BASE_FEE = 1000000000 71MAX_OMMER_DEPTH = 6 72BOMB_DELAY_BLOCKS = 9700000 73EMPTY_OMMER_HASH = keccak256(rlp.encode([])) 74 75 76@dataclass 77class BlockChain: 78 """ 79 History and current state of the block chain. 80 """ 81 82 blocks: List[Block] 83 state: State 84 chain_id: U64 85 86 87def apply_fork(old: BlockChain) -> BlockChain: 88 """ 89 Transforms the state from the previous hard fork (`old`) into the block 90 chain object for this hard fork and returns it. 91 92 When forks need to implement an irregular state transition, this function 93 is used to handle the irregularity. See the :ref:`DAO Fork <dao-fork>` for 94 an example. 95 96 Parameters 97 ---------- 98 old : 99 Previous block chain object. 100 101 Returns 102 ------- 103 new : `BlockChain` 104 Upgraded block chain object for this hard fork. 105 """ 106 return old 107 108 109def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: 110 """ 111 Obtain the list of hashes of the previous 256 blocks in order of 112 increasing block number. 113 114 This function will return less hashes for the first 256 blocks. 115 116 The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, 117 therefore this function retrieves them. 118 119 Parameters 120 ---------- 121 chain : 122 History and current state. 123 124 Returns 125 ------- 126 recent_block_hashes : `List[Hash32]` 127 Hashes of the recent 256 blocks in order of increasing block number. 128 """ 129 recent_blocks = chain.blocks[-255:] 130 # TODO: This function has not been tested rigorously 131 if len(recent_blocks) == 0: 132 return [] 133 134 recent_block_hashes = [] 135 136 for block in recent_blocks: 137 prev_block_hash = block.header.parent_hash 138 recent_block_hashes.append(prev_block_hash) 139 140 # We are computing the hash only for the most recent block and not for 141 # the rest of the blocks as they have successors which have the hash of 142 # the current block as parent hash. 143 most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) 144 recent_block_hashes.append(most_recent_block_hash) 145 146 return recent_block_hashes 147 148 149def state_transition(chain: BlockChain, block: Block) -> None: 150 """ 151 Attempts to apply a block to an existing block chain. 152 153 All parts of the block's contents need to be verified before being added 154 to the chain. Blocks are verified by ensuring that the contents of the 155 block make logical sense with the contents of the parent block. The 156 information in the block's header must also match the corresponding 157 information in the block. 158 159 To implement Ethereum, in theory clients are only required to store the 160 most recent 255 blocks of the chain since as far as execution is 161 concerned, only those blocks are accessed. Practically, however, clients 162 should store more blocks to handle reorgs. 163 164 Parameters 165 ---------- 166 chain : 167 History and current state. 168 block : 169 Block to apply to `chain`. 170 """ 171 parent_header = chain.blocks[-1].header 172 validate_header(block.header, parent_header) 173 validate_ommers(block.ommers, block.header, chain) 174 ( 175 gas_used, 176 transactions_root, 177 receipt_root, 178 block_logs_bloom, 179 state, 180 ) = apply_body( 181 chain.state, 182 get_last_256_block_hashes(chain), 183 block.header.coinbase, 184 block.header.number, 185 block.header.base_fee_per_gas, 186 block.header.gas_limit, 187 block.header.timestamp, 188 block.header.difficulty, 189 block.transactions, 190 block.ommers, 191 chain.chain_id, 192 ) 193 ensure(gas_used == block.header.gas_used, InvalidBlock) 194 ensure(transactions_root == block.header.transactions_root, InvalidBlock) 195 ensure(state_root(state) == block.header.state_root, InvalidBlock) 196 ensure(receipt_root == block.header.receipt_root, InvalidBlock) 197 ensure(block_logs_bloom == block.header.bloom, InvalidBlock) 198 199 chain.blocks.append(block) 200 if len(chain.blocks) > 255: 201 # Real clients have to store more blocks to deal with reorgs, but the 202 # protocol only requires the last 255 203 chain.blocks = chain.blocks[-255:] 204 205 206def calculate_base_fee_per_gas( 207 block_gas_limit: Uint, 208 parent_gas_limit: Uint, 209 parent_gas_used: Uint, 210 parent_base_fee_per_gas: Uint, 211 is_fork_block: bool, 212) -> Uint: 213 """ 214 Calculates the base fee per gas for the block. 215 216 Parameters 217 ---------- 218 block_gas_limit : 219 Gas limit of the block for which the base fee is being calculated. 220 parent_gas_limit : 221 Gas limit of the parent block. 222 parent_gas_used : 223 Gas used in the parent block. 224 parent_base_fee_per_gas : 225 Base fee per gas of the parent block. 226 is_fork_block : 227 Whether the block is the fork block. 228 229 Returns 230 ------- 231 base_fee_per_gas : `Uint` 232 Base fee per gas for the block. 233 """ 234 if is_fork_block: 235 return Uint(INITIAL_BASE_FEE) 236 parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER 237 238 ensure( 239 check_gas_limit(block_gas_limit, parent_gas_limit), 240 InvalidBlock, 241 ) 242 243 if parent_gas_used == parent_gas_target: 244 expected_base_fee_per_gas = parent_base_fee_per_gas 245 elif parent_gas_used > parent_gas_target: 246 gas_used_delta = parent_gas_used - parent_gas_target 247 248 parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta 249 target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target 250 251 base_fee_per_gas_delta = max( 252 target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR, 253 1, 254 ) 255 256 expected_base_fee_per_gas = ( 257 parent_base_fee_per_gas + base_fee_per_gas_delta 258 ) 259 else: 260 gas_used_delta = parent_gas_target - parent_gas_used 261 262 parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta 263 target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target 264 265 base_fee_per_gas_delta = ( 266 target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR 267 ) 268 269 expected_base_fee_per_gas = ( 270 parent_base_fee_per_gas - base_fee_per_gas_delta 271 ) 272 273 return Uint(expected_base_fee_per_gas) 274 275 276def validate_header(header: Header, parent_header: Header) -> None: 277 """ 278 Verifies a block header. 279 280 In order to consider a block's header valid, the logic for the 281 quantities in the header should match the logic for the block itself. 282 For example the header timestamp should be greater than the block's parent 283 timestamp because the block was created *after* the parent block. 284 Additionally, the block's number should be directly following the parent 285 block's number since it is the next block in the sequence. 286 287 Parameters 288 ---------- 289 header : 290 Header to check for correctness. 291 parent_header : 292 Parent Header of the header to check for correctness 293 """ 294 ensure(header.gas_used <= header.gas_limit, InvalidBlock) 295 296 is_fork_block = header.number == FORK_CRITERIA.block_number 297 expected_base_fee_per_gas = calculate_base_fee_per_gas( 298 header.gas_limit, 299 parent_header.gas_limit, 300 parent_header.gas_used, 301 parent_header.base_fee_per_gas, 302 is_fork_block, 303 ) 304 305 ensure(expected_base_fee_per_gas == header.base_fee_per_gas, InvalidBlock) 306 307 parent_has_ommers = parent_header.ommers_hash != EMPTY_OMMER_HASH 308 ensure(header.timestamp > parent_header.timestamp, InvalidBlock) 309 ensure(header.number == parent_header.number + 1, InvalidBlock) 310 ensure(len(header.extra_data) <= 32, InvalidBlock) 311 312 block_difficulty = calculate_block_difficulty( 313 header.number, 314 header.timestamp, 315 parent_header.timestamp, 316 parent_header.difficulty, 317 parent_has_ommers, 318 ) 319 ensure(header.difficulty == block_difficulty, InvalidBlock) 320 321 block_parent_hash = keccak256(rlp.encode(parent_header)) 322 ensure(header.parent_hash == block_parent_hash, InvalidBlock) 323 324 validate_proof_of_work(header) 325 326 327def generate_header_hash_for_pow(header: Header) -> Hash32: 328 """ 329 Generate rlp hash of the header which is to be used for Proof-of-Work 330 verification. 331 332 In other words, the PoW artefacts `mix_digest` and `nonce` are ignored 333 while calculating this hash. 334 335 A particular PoW is valid for a single hash, that hash is computed by 336 this function. The `nonce` and `mix_digest` are omitted from this hash 337 because they are being changed by miners in their search for a sufficient 338 proof-of-work. 339 340 Parameters 341 ---------- 342 header : 343 The header object for which the hash is to be generated. 344 345 Returns 346 ------- 347 hash : `Hash32` 348 The PoW valid rlp hash of the passed in header. 349 """ 350 header_data_without_pow_artefacts = [ 351 header.parent_hash, 352 header.ommers_hash, 353 header.coinbase, 354 header.state_root, 355 header.transactions_root, 356 header.receipt_root, 357 header.bloom, 358 header.difficulty, 359 header.number, 360 header.gas_limit, 361 header.gas_used, 362 header.timestamp, 363 header.extra_data, 364 header.base_fee_per_gas, 365 ] 366 367 return rlp.rlp_hash(header_data_without_pow_artefacts) 368 369 370def validate_proof_of_work(header: Header) -> None: 371 """ 372 Validates the Proof of Work constraints. 373 374 In order to verify that a miner's proof-of-work is valid for a block, a 375 ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` 376 hash function. The mix digest is a hash of the header and the nonce that 377 is passed through and it confirms whether or not proof-of-work was done 378 on the correct block. The result is the actual hash value of the block. 379 380 Parameters 381 ---------- 382 header : 383 Header of interest. 384 """ 385 header_hash = generate_header_hash_for_pow(header) 386 # TODO: Memoize this somewhere and read from that data instead of 387 # calculating cache for every block validation. 388 cache = generate_cache(header.number) 389 mix_digest, result = hashimoto_light( 390 header_hash, header.nonce, cache, dataset_size(header.number) 391 ) 392 393 ensure(mix_digest == header.mix_digest, InvalidBlock) 394 ensure( 395 Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), 396 InvalidBlock, 397 ) 398 399 400def check_transaction( 401 tx: Transaction, 402 base_fee_per_gas: Uint, 403 gas_available: Uint, 404 chain_id: U64, 405) -> Tuple[Address, Uint]: 406 """ 407 Check if the transaction is includable in the block. 408 409 Parameters 410 ---------- 411 tx : 412 The transaction. 413 base_fee_per_gas : 414 The block base fee. 415 gas_available : 416 The gas remaining in the block. 417 chain_id : 418 The ID of the current chain. 419 420 Returns 421 ------- 422 sender_address : 423 The sender of the transaction. 424 effective_gas_price : 425 The price to charge for gas when the transaction is executed. 426 427 Raises 428 ------ 429 InvalidBlock : 430 If the transaction is not includable. 431 """ 432 ensure(tx.gas <= gas_available, InvalidBlock) 433 sender_address = recover_sender(chain_id, tx) 434 435 if isinstance(tx, FeeMarketTransaction): 436 ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock) 437 ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock) 438 439 priority_fee_per_gas = min( 440 tx.max_priority_fee_per_gas, 441 tx.max_fee_per_gas - base_fee_per_gas, 442 ) 443 effective_gas_price = priority_fee_per_gas + base_fee_per_gas 444 else: 445 ensure(tx.gas_price >= base_fee_per_gas, InvalidBlock) 446 effective_gas_price = tx.gas_price 447 448 return sender_address, effective_gas_price 449 450 451def make_receipt( 452 tx: Transaction, 453 error: Optional[Exception], 454 cumulative_gas_used: Uint, 455 logs: Tuple[Log, ...], 456) -> Union[Bytes, Receipt]: 457 """ 458 Make the receipt for a transaction that was executed. 459 460 Parameters 461 ---------- 462 tx : 463 The executed transaction. 464 error : 465 Error in the top level frame of the transaction, if any. 466 cumulative_gas_used : 467 The total gas used so far in the block after the transaction was 468 executed. 469 logs : 470 The logs produced by the transaction. 471 472 Returns 473 ------- 474 receipt : 475 The receipt for the transaction. 476 """ 477 receipt = Receipt( 478 succeeded=error is None, 479 cumulative_gas_used=cumulative_gas_used, 480 bloom=logs_bloom(logs), 481 logs=logs, 482 ) 483 484 if isinstance(tx, AccessListTransaction): 485 return b"\x01" + rlp.encode(receipt) 486 elif isinstance(tx, FeeMarketTransaction): 487 return b"\x02" + rlp.encode(receipt) 488 else: 489 return receipt 490 491 492def apply_body( 493 state: State, 494 block_hashes: List[Hash32], 495 coinbase: Address, 496 block_number: Uint, 497 base_fee_per_gas: Uint, 498 block_gas_limit: Uint, 499 block_time: U256, 500 block_difficulty: Uint, 501 transactions: Tuple[Union[LegacyTransaction, Bytes], ...], 502 ommers: Tuple[Header, ...], 503 chain_id: U64, 504) -> Tuple[Uint, Root, Root, Bloom, State]: 505 """ 506 Executes a block. 507 508 Many of the contents of a block are stored in data structures called 509 tries. There is a transactions trie which is similar to a ledger of the 510 transactions stored in the current block. There is also a receipts trie 511 which stores the results of executing a transaction, like the post state 512 and gas used. This function creates and executes the block that is to be 513 added to the chain. 514 515 Parameters 516 ---------- 517 state : 518 Current account state. 519 block_hashes : 520 List of hashes of the previous 256 blocks in the order of 521 increasing block number. 522 coinbase : 523 Address of account which receives block reward and transaction fees. 524 block_number : 525 Position of the block within the chain. 526 base_fee_per_gas : 527 Base fee per gas of within the block. 528 block_gas_limit : 529 Initial amount of gas available for execution in this block. 530 block_time : 531 Time the block was produced, measured in seconds since the epoch. 532 block_difficulty : 533 Difficulty of the block. 534 transactions : 535 Transactions included in the block. 536 ommers : 537 Headers of ancestor blocks which are not direct parents (formerly 538 uncles.) 539 chain_id : 540 ID of the executing chain. 541 542 Returns 543 ------- 544 block_gas_used : `ethereum.base_types.Uint` 545 Gas used for executing all transactions. 546 transactions_root : `ethereum.fork_types.Root` 547 Trie root of all the transactions in the block. 548 receipt_root : `ethereum.fork_types.Root` 549 Trie root of all the receipts in the block. 550 block_logs_bloom : `Bloom` 551 Logs bloom of all the logs included in all the transactions of the 552 block. 553 state : `ethereum.fork_types.State` 554 State after all transactions have been executed. 555 """ 556 gas_available = block_gas_limit 557 transactions_trie: Trie[ 558 Bytes, Optional[Union[Bytes, LegacyTransaction]] 559 ] = Trie(secured=False, default=None) 560 receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie( 561 secured=False, default=None 562 ) 563 block_logs: Tuple[Log, ...] = () 564 565 for i, tx in enumerate(map(decode_transaction, transactions)): 566 trie_set( 567 transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx) 568 ) 569 570 sender_address, effective_gas_price = check_transaction( 571 tx, base_fee_per_gas, gas_available, chain_id 572 ) 573 574 env = vm.Environment( 575 caller=sender_address, 576 origin=sender_address, 577 block_hashes=block_hashes, 578 coinbase=coinbase, 579 number=block_number, 580 gas_limit=block_gas_limit, 581 base_fee_per_gas=base_fee_per_gas, 582 gas_price=effective_gas_price, 583 time=block_time, 584 difficulty=block_difficulty, 585 state=state, 586 chain_id=chain_id, 587 traces=[], 588 ) 589 590 gas_used, logs, error = process_transaction(env, tx) 591 gas_available -= gas_used 592 593 receipt = make_receipt( 594 tx, error, (block_gas_limit - gas_available), logs 595 ) 596 597 trie_set( 598 receipts_trie, 599 rlp.encode(Uint(i)), 600 receipt, 601 ) 602 603 block_logs += logs 604 605 pay_rewards(state, block_number, coinbase, ommers) 606 607 block_gas_used = block_gas_limit - gas_available 608 609 block_logs_bloom = logs_bloom(block_logs) 610 611 return ( 612 block_gas_used, 613 root(transactions_trie), 614 root(receipts_trie), 615 block_logs_bloom, 616 state, 617 ) 618 619 620def validate_ommers( 621 ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain 622) -> None: 623 """ 624 Validates the ommers mentioned in the block. 625 626 An ommer block is a block that wasn't canonically added to the 627 blockchain because it wasn't validated as fast as the canonical block 628 but was mined at the same time. 629 630 To be considered valid, the ommers must adhere to the rules defined in 631 the Ethereum protocol. The maximum amount of ommers is 2 per block and 632 there cannot be duplicate ommers in a block. Many of the other ommer 633 constraints are listed in the in-line comments of this function. 634 635 Parameters 636 ---------- 637 ommers : 638 List of ommers mentioned in the current block. 639 block_header: 640 The header of current block. 641 chain : 642 History and current state. 643 """ 644 block_hash = rlp.rlp_hash(block_header) 645 646 ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) 647 648 if len(ommers) == 0: 649 # Nothing to validate 650 return 651 652 # Check that each ommer satisfies the constraints of a header 653 for ommer in ommers: 654 ensure(1 <= ommer.number < block_header.number, InvalidBlock) 655 ommer_parent_header = chain.blocks[ 656 -(block_header.number - ommer.number) - 1 657 ].header 658 validate_header(ommer, ommer_parent_header) 659 660 # Check that there can be only at most 2 ommers for a block. 661 ensure(len(ommers) <= 2, InvalidBlock) 662 663 ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] 664 # Check that there are no duplicates in the ommers of current block 665 ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) 666 667 recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] 668 recent_canonical_block_hashes = { 669 rlp.rlp_hash(block.header) for block in recent_canonical_blocks 670 } 671 recent_ommers_hashes: Set[Hash32] = set() 672 for block in recent_canonical_blocks: 673 recent_ommers_hashes = recent_ommers_hashes.union( 674 {rlp.rlp_hash(ommer) for ommer in block.ommers} 675 ) 676 677 for ommer_index, ommer in enumerate(ommers): 678 ommer_hash = ommers_hashes[ommer_index] 679 # The current block shouldn't be the ommer 680 ensure(ommer_hash != block_hash, InvalidBlock) 681 682 # Ommer shouldn't be one of the recent canonical blocks 683 ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) 684 685 # Ommer shouldn't be one of the uncles mentioned in the recent 686 # canonical blocks 687 ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) 688 689 # Ommer age with respect to the current block. For example, an age of 690 # 1 indicates that the ommer is a sibling of previous block. 691 ommer_age = block_header.number - ommer.number 692 ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) 693 694 ensure( 695 ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock 696 ) 697 ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock) 698 699 700def pay_rewards( 701 state: State, 702 block_number: Uint, 703 coinbase: Address, 704 ommers: Tuple[Header, ...], 705) -> None: 706 """ 707 Pay rewards to the block miner as well as the ommers miners. 708 709 The miner of the canonical block is rewarded with the predetermined 710 block reward, ``BLOCK_REWARD``, plus a variable award based off of the 711 number of ommer blocks that were mined around the same time, and included 712 in the canonical block's header. An ommer block is a block that wasn't 713 added to the canonical blockchain because it wasn't validated as fast as 714 the accepted block but was mined at the same time. Although not all blocks 715 that are mined are added to the canonical chain, miners are still paid a 716 reward for their efforts. This reward is called an ommer reward and is 717 calculated based on the number associated with the ommer block that they 718 mined. 719 720 Parameters 721 ---------- 722 state : 723 Current account state. 724 block_number : 725 Position of the block within the chain. 726 coinbase : 727 Address of account which receives block reward and transaction fees. 728 ommers : 729 List of ommers mentioned in the current block. 730 """ 731 miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) 732 create_ether(state, coinbase, miner_reward) 733 734 for ommer in ommers: 735 # Ommer age with respect to the current block. 736 ommer_age = U256(block_number - ommer.number) 737 ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 738 create_ether(state, ommer.coinbase, ommer_miner_reward) 739 740 741def process_transaction( 742 env: vm.Environment, tx: Transaction 743) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: 744 """ 745 Execute a transaction against the provided environment. 746 747 This function processes the actions needed to execute a transaction. 748 It decrements the sender's account after calculating the gas fee and 749 refunds them the proper amount after execution. Calling contracts, 750 deploying code, and incrementing nonces are all examples of actions that 751 happen within this function or from a call made within this function. 752 753 Accounts that are marked for deletion are processed and destroyed after 754 execution. 755 756 Parameters 757 ---------- 758 env : 759 Environment for the Ethereum Virtual Machine. 760 tx : 761 Transaction to execute. 762 763 Returns 764 ------- 765 gas_left : `ethereum.base_types.U256` 766 Remaining gas after execution. 767 logs : `Tuple[ethereum.fork_types.Log, ...]` 768 Logs generated during execution. 769 """ 770 ensure(validate_transaction(tx), InvalidBlock) 771 772 sender = env.origin 773 sender_account = get_account(env.state, sender) 774 775 if isinstance(tx, FeeMarketTransaction): 776 max_gas_fee = tx.gas * tx.max_fee_per_gas 777 else: 778 max_gas_fee = tx.gas * tx.gas_price 779 780 ensure(sender_account.nonce == tx.nonce, InvalidBlock) 781 ensure(sender_account.balance >= max_gas_fee + tx.value, InvalidBlock) 782 ensure(sender_account.code == bytearray(), InvalidBlock) 783 784 effective_gas_fee = tx.gas * env.gas_price 785 786 gas = tx.gas - calculate_intrinsic_cost(tx) 787 increment_nonce(env.state, sender) 788 789 sender_balance_after_gas_fee = sender_account.balance - effective_gas_fee 790 set_account_balance(env.state, sender, sender_balance_after_gas_fee) 791 792 preaccessed_addresses = set() 793 preaccessed_storage_keys = set() 794 if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): 795 for address, keys in tx.access_list: 796 preaccessed_addresses.add(address) 797 for key in keys: 798 preaccessed_storage_keys.add((address, key)) 799 800 message = prepare_message( 801 sender, 802 tx.to, 803 tx.value, 804 tx.data, 805 gas, 806 env, 807 preaccessed_addresses=frozenset(preaccessed_addresses), 808 preaccessed_storage_keys=frozenset(preaccessed_storage_keys), 809 ) 810 811 output = process_message_call(message, env) 812 813 gas_used = tx.gas - output.gas_left 814 gas_refund = min(gas_used // 5, output.refund_counter) 815 gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price 816 817 # For non-1559 transactions env.gas_price == tx.gas_price 818 priority_fee_per_gas = env.gas_price - env.base_fee_per_gas 819 transaction_fee = ( 820 tx.gas - output.gas_left - gas_refund 821 ) * priority_fee_per_gas 822 823 total_gas_used = gas_used - gas_refund 824 825 # refund gas 826 sender_balance_after_refund = ( 827 get_account(env.state, sender).balance + gas_refund_amount 828 ) 829 set_account_balance(env.state, sender, sender_balance_after_refund) 830 831 # transfer miner fees 832 coinbase_balance_after_mining_fee = ( 833 get_account(env.state, env.coinbase).balance + transaction_fee 834 ) 835 if coinbase_balance_after_mining_fee != 0: 836 set_account_balance( 837 env.state, env.coinbase, coinbase_balance_after_mining_fee 838 ) 839 elif account_exists_and_is_empty(env.state, env.coinbase): 840 destroy_account(env.state, env.coinbase) 841 842 for address in output.accounts_to_delete: 843 destroy_account(env.state, address) 844 845 for address in output.touched_accounts: 846 if account_exists_and_is_empty(env.state, address): 847 destroy_account(env.state, address) 848 849 return total_gas_used, output.logs, output.error 850 851 852def validate_transaction(tx: Transaction) -> bool: 853 """ 854 Verifies a transaction. 855 856 The gas in a transaction gets used to pay for the intrinsic cost of 857 operations, therefore if there is insufficient gas then it would not 858 be possible to execute a transaction and it will be declared invalid. 859 860 Additionally, the nonce of a transaction must not equal or exceed the 861 limit defined in `EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>`_. 862 In practice, defining the limit as ``2**64-1`` has no impact because 863 sending ``2**64-1`` transactions is improbable. It's not strictly 864 impossible though, ``2**64-1`` transactions is the entire capacity of the 865 Ethereum blockchain at 2022 gas limits for a little over 22 years. 866 867 Parameters 868 ---------- 869 tx : 870 Transaction to validate. 871 872 Returns 873 ------- 874 verified : `bool` 875 True if the transaction can be executed, or False otherwise. 876 """ 877 return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1 878 879 880def calculate_intrinsic_cost(tx: Transaction) -> Uint: 881 """ 882 Calculates the gas that is charged before execution is started. 883 884 The intrinsic cost of the transaction is charged before execution has 885 begun. Functions/operations in the EVM cost money to execute so this 886 intrinsic cost is for the operations that need to be paid for as part of 887 the transaction. Data transfer, for example, is part of this intrinsic 888 cost. It costs ether to send data over the wire and that ether is 889 accounted for in the intrinsic cost calculated in this function. This 890 intrinsic cost must be calculated and paid for before execution in order 891 for all operations to be implemented. 892 893 Parameters 894 ---------- 895 tx : 896 Transaction to compute the intrinsic cost of. 897 898 Returns 899 ------- 900 verified : `ethereum.base_types.Uint` 901 The intrinsic cost of the transaction. 902 """ 903 data_cost = 0 904 905 for byte in tx.data: 906 if byte == 0: 907 data_cost += TX_DATA_COST_PER_ZERO 908 else: 909 data_cost += TX_DATA_COST_PER_NON_ZERO 910 911 if tx.to == Bytes0(b""): 912 create_cost = TX_CREATE_COST 913 else: 914 create_cost = 0 915 916 access_list_cost = 0 917 if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): 918 for _address, keys in tx.access_list: 919 access_list_cost += TX_ACCESS_LIST_ADDRESS_COST 920 access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST 921 922 return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) 923 924 925def recover_sender(chain_id: U64, tx: Transaction) -> Address: 926 """ 927 Extracts the sender address from a transaction. 928 929 The v, r, and s values are the three parts that make up the signature 930 of a transaction. In order to recover the sender of a transaction the two 931 components needed are the signature (``v``, ``r``, and ``s``) and the 932 signing hash of the transaction. The sender's public key can be obtained 933 with these two values and therefore the sender address can be retrieved. 934 935 Parameters 936 ---------- 937 tx : 938 Transaction of interest. 939 chain_id : 940 ID of the executing chain. 941 942 Returns 943 ------- 944 sender : `ethereum.fork_types.Address` 945 The address of the account that signed the transaction. 946 """ 947 r, s = tx.r, tx.s 948 949 ensure(0 < r and r < SECP256K1N, InvalidBlock) 950 ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) 951 952 if isinstance(tx, LegacyTransaction): 953 v = tx.v 954 if v == 27 or v == 28: 955 public_key = secp256k1_recover( 956 r, s, v - 27, signing_hash_pre155(tx) 957 ) 958 else: 959 ensure( 960 v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock 961 ) 962 public_key = secp256k1_recover( 963 r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) 964 ) 965 elif isinstance(tx, AccessListTransaction): 966 public_key = secp256k1_recover( 967 r, s, tx.y_parity, signing_hash_2930(tx) 968 ) 969 elif isinstance(tx, FeeMarketTransaction): 970 public_key = secp256k1_recover( 971 r, s, tx.y_parity, signing_hash_1559(tx) 972 ) 973 974 return Address(keccak256(public_key)[12:32]) 975 976 977def signing_hash_pre155(tx: LegacyTransaction) -> Hash32: 978 """ 979 Compute the hash of a transaction used in a legacy (pre EIP 155) signature. 980 981 Parameters 982 ---------- 983 tx : 984 Transaction of interest. 985 986 Returns 987 ------- 988 hash : `ethereum.crypto.hash.Hash32` 989 Hash of the transaction. 990 """ 991 return keccak256( 992 rlp.encode( 993 ( 994 tx.nonce, 995 tx.gas_price, 996 tx.gas, 997 tx.to, 998 tx.value, 999 tx.data, 1000 ) 1001 ) 1002 ) 1003 1004 1005def signing_hash_155(tx: LegacyTransaction, chain_id: U64) -> Hash32: 1006 """ 1007 Compute the hash of a transaction used in a EIP 155 signature. 1008 1009 Parameters 1010 ---------- 1011 tx : 1012 Transaction of interest. 1013 chain_id : 1014 The id of the current chain. 1015 1016 Returns 1017 ------- 1018 hash : `ethereum.crypto.hash.Hash32` 1019 Hash of the transaction. 1020 """ 1021 return keccak256( 1022 rlp.encode( 1023 ( 1024 tx.nonce, 1025 tx.gas_price, 1026 tx.gas, 1027 tx.to, 1028 tx.value, 1029 tx.data, 1030 chain_id, 1031 Uint(0), 1032 Uint(0), 1033 ) 1034 ) 1035 ) 1036 1037 1038def signing_hash_2930(tx: AccessListTransaction) -> Hash32: 1039 """ 1040 Compute the hash of a transaction used in a EIP 2930 signature. 1041 1042 Parameters 1043 ---------- 1044 tx : 1045 Transaction of interest. 1046 1047 Returns 1048 ------- 1049 hash : `ethereum.crypto.hash.Hash32` 1050 Hash of the transaction. 1051 """ 1052 return keccak256( 1053 b"\x01" 1054 + rlp.encode( 1055 ( 1056 tx.chain_id, 1057 tx.nonce, 1058 tx.gas_price, 1059 tx.gas, 1060 tx.to, 1061 tx.value, 1062 tx.data, 1063 tx.access_list, 1064 ) 1065 ) 1066 ) 1067 1068 1069def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32: 1070 """ 1071 Compute the hash of a transaction used in a EIP 1559 signature. 1072 1073 Parameters 1074 ---------- 1075 tx : 1076 Transaction of interest. 1077 1078 Returns 1079 ------- 1080 hash : `ethereum.crypto.hash.Hash32` 1081 Hash of the transaction. 1082 """ 1083 return keccak256( 1084 b"\x02" 1085 + rlp.encode( 1086 ( 1087 tx.chain_id, 1088 tx.nonce, 1089 tx.max_priority_fee_per_gas, 1090 tx.max_fee_per_gas, 1091 tx.gas, 1092 tx.to, 1093 tx.value, 1094 tx.data, 1095 tx.access_list, 1096 ) 1097 ) 1098 ) 1099 1100 1101def compute_header_hash(header: Header) -> Hash32: 1102 """ 1103 Computes the hash of a block header. 1104 1105 The header hash of a block is the canonical hash that is used to refer 1106 to a specific block and completely distinguishes a block from another. 1107 1108 ``keccak256`` is a function that produces a 256 bit hash of any input. 1109 It also takes in any number of bytes as an input and produces a single 1110 hash for them. A hash is a completely unique output for a single input. 1111 So an input corresponds to one unique hash that can be used to identify 1112 the input exactly. 1113 1114 Prior to using the ``keccak256`` hash function, the header must be 1115 encoded using the Recursive-Length Prefix. See :ref:`rlp`. 1116 RLP encoding the header converts it into a space-efficient format that 1117 allows for easy transfer of data between nodes. The purpose of RLP is to 1118 encode arbitrarily nested arrays of binary data, and RLP is the primary 1119 encoding method used to serialize objects in Ethereum's execution layer. 1120 The only purpose of RLP is to encode structure; encoding specific data 1121 types (e.g. strings, floats) is left up to higher-order protocols. 1122 1123 Parameters 1124 ---------- 1125 header : 1126 Header of interest. 1127 1128 Returns 1129 ------- 1130 hash : `ethereum.crypto.hash.Hash32` 1131 Hash of the header. 1132 """ 1133 return keccak256(rlp.encode(header)) 1134 1135 1136def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: 1137 """ 1138 Validates the gas limit for a block. 1139 1140 The bounds of the gas limit, ``max_adjustment_delta``, is set as the 1141 quotient of the parent block's gas limit and the 1142 ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is 1143 passed through as a parameter is greater than or equal to the *sum* of 1144 the parent's gas and the adjustment delta then the limit for gas is too 1145 high and fails this function's check. Similarly, if the limit is less 1146 than or equal to the *difference* of the parent's gas and the adjustment 1147 delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's 1148 check fails because the gas limit doesn't allow for a sufficient or 1149 reasonable amount of gas to be used on a block. 1150 1151 Parameters 1152 ---------- 1153 gas_limit : 1154 Gas limit to validate. 1155 1156 parent_gas_limit : 1157 Gas limit of the parent block. 1158 1159 Returns 1160 ------- 1161 check : `bool` 1162 True if gas limit constraints are satisfied, False otherwise. 1163 """ 1164 max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR 1165 if gas_limit >= parent_gas_limit + max_adjustment_delta: 1166 return False 1167 if gas_limit <= parent_gas_limit - max_adjustment_delta: 1168 return False 1169 if gas_limit < GAS_LIMIT_MINIMUM: 1170 return False 1171 1172 return True 1173 1174 1175def calculate_block_difficulty( 1176 block_number: Uint, 1177 block_timestamp: U256, 1178 parent_timestamp: U256, 1179 parent_difficulty: Uint, 1180 parent_has_ommers: bool, 1181) -> Uint: 1182 """ 1183 Computes difficulty of a block using its header and parent header. 1184 1185 The difficulty is determined by the time the block was created after its 1186 parent. The ``offset`` is calculated using the parent block's difficulty, 1187 ``parent_difficulty``, and the timestamp between blocks. This offset is 1188 then added to the parent difficulty and is stored as the ``difficulty`` 1189 variable. If the time between the block and its parent is too short, the 1190 offset will result in a positive number thus making the sum of 1191 ``parent_difficulty`` and ``offset`` to be a greater value in order to 1192 avoid mass forking. But, if the time is long enough, then the offset 1193 results in a negative value making the block less difficult than 1194 its parent. 1195 1196 The base standard for a block's difficulty is the predefined value 1197 set for the genesis block since it has no parent. So, a block 1198 can't be less difficult than the genesis block, therefore each block's 1199 difficulty is set to the maximum value between the calculated 1200 difficulty and the ``GENESIS_DIFFICULTY``. 1201 1202 Parameters 1203 ---------- 1204 block_number : 1205 Block number of the block. 1206 block_timestamp : 1207 Timestamp of the block. 1208 parent_timestamp : 1209 Timestamp of the parent block. 1210 parent_difficulty : 1211 difficulty of the parent block. 1212 parent_has_ommers: 1213 does the parent have ommers. 1214 1215 Returns 1216 ------- 1217 difficulty : `ethereum.base_types.Uint` 1218 Computed difficulty for a block. 1219 """ 1220 offset = ( 1221 int(parent_difficulty) 1222 // 2048 1223 * max( 1224 (2 if parent_has_ommers else 1) 1225 - int(block_timestamp - parent_timestamp) // 9, 1226 -99, 1227 ) 1228 ) 1229 difficulty = int(parent_difficulty) + offset 1230 # Historical Note: The difficulty bomb was not present in Ethereum at the 1231 # start of Frontier, but was added shortly after launch. However since the 1232 # bomb has no effect prior to block 200000 we pretend it existed from 1233 # genesis. 1234 # See https://github.com/ethereum/go-ethereum/pull/1588 1235 num_bomb_periods = ((int(block_number) - BOMB_DELAY_BLOCKS) // 100000) - 2 1236 if num_bomb_periods >= 0: 1237 difficulty += 2**num_bomb_periods 1238 1239 # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding 1240 # the bomb. This bug does not matter because the difficulty is always much 1241 # greater than `MINIMUM_DIFFICULTY` on Mainnet. 1242 return Uint(max(difficulty, MINIMUM_DIFFICULTY))
77@dataclass 78class BlockChain: 79 """ 80 History and current state of the block chain. 81 """ 82 83 blocks: List[Block] 84 state: State 85 chain_id: U64
History and current state of the block chain.
88def apply_fork(old: BlockChain) -> BlockChain: 89 """ 90 Transforms the state from the previous hard fork (`old`) into the block 91 chain object for this hard fork and returns it. 92 93 When forks need to implement an irregular state transition, this function 94 is used to handle the irregularity. See the :ref:`DAO Fork <dao-fork>` for 95 an example. 96 97 Parameters 98 ---------- 99 old : 100 Previous block chain object. 101 102 Returns 103 ------- 104 new : `BlockChain` 105 Upgraded block chain object for this hard fork. 106 """ 107 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.
110def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]: 111 """ 112 Obtain the list of hashes of the previous 256 blocks in order of 113 increasing block number. 114 115 This function will return less hashes for the first 256 blocks. 116 117 The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, 118 therefore this function retrieves them. 119 120 Parameters 121 ---------- 122 chain : 123 History and current state. 124 125 Returns 126 ------- 127 recent_block_hashes : `List[Hash32]` 128 Hashes of the recent 256 blocks in order of increasing block number. 129 """ 130 recent_blocks = chain.blocks[-255:] 131 # TODO: This function has not been tested rigorously 132 if len(recent_blocks) == 0: 133 return [] 134 135 recent_block_hashes = [] 136 137 for block in recent_blocks: 138 prev_block_hash = block.header.parent_hash 139 recent_block_hashes.append(prev_block_hash) 140 141 # We are computing the hash only for the most recent block and not for 142 # the rest of the blocks as they have successors which have the hash of 143 # the current block as parent hash. 144 most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header)) 145 recent_block_hashes.append(most_recent_block_hash) 146 147 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.
150def state_transition(chain: BlockChain, block: Block) -> None: 151 """ 152 Attempts to apply a block to an existing block chain. 153 154 All parts of the block's contents need to be verified before being added 155 to the chain. Blocks are verified by ensuring that the contents of the 156 block make logical sense with the contents of the parent block. The 157 information in the block's header must also match the corresponding 158 information in the block. 159 160 To implement Ethereum, in theory clients are only required to store the 161 most recent 255 blocks of the chain since as far as execution is 162 concerned, only those blocks are accessed. Practically, however, clients 163 should store more blocks to handle reorgs. 164 165 Parameters 166 ---------- 167 chain : 168 History and current state. 169 block : 170 Block to apply to `chain`. 171 """ 172 parent_header = chain.blocks[-1].header 173 validate_header(block.header, parent_header) 174 validate_ommers(block.ommers, block.header, chain) 175 ( 176 gas_used, 177 transactions_root, 178 receipt_root, 179 block_logs_bloom, 180 state, 181 ) = apply_body( 182 chain.state, 183 get_last_256_block_hashes(chain), 184 block.header.coinbase, 185 block.header.number, 186 block.header.base_fee_per_gas, 187 block.header.gas_limit, 188 block.header.timestamp, 189 block.header.difficulty, 190 block.transactions, 191 block.ommers, 192 chain.chain_id, 193 ) 194 ensure(gas_used == block.header.gas_used, InvalidBlock) 195 ensure(transactions_root == block.header.transactions_root, InvalidBlock) 196 ensure(state_root(state) == block.header.state_root, InvalidBlock) 197 ensure(receipt_root == block.header.receipt_root, InvalidBlock) 198 ensure(block_logs_bloom == block.header.bloom, InvalidBlock) 199 200 chain.blocks.append(block) 201 if len(chain.blocks) > 255: 202 # Real clients have to store more blocks to deal with reorgs, but the 203 # protocol only requires the last 255 204 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
.
207def calculate_base_fee_per_gas( 208 block_gas_limit: Uint, 209 parent_gas_limit: Uint, 210 parent_gas_used: Uint, 211 parent_base_fee_per_gas: Uint, 212 is_fork_block: bool, 213) -> Uint: 214 """ 215 Calculates the base fee per gas for the block. 216 217 Parameters 218 ---------- 219 block_gas_limit : 220 Gas limit of the block for which the base fee is being calculated. 221 parent_gas_limit : 222 Gas limit of the parent block. 223 parent_gas_used : 224 Gas used in the parent block. 225 parent_base_fee_per_gas : 226 Base fee per gas of the parent block. 227 is_fork_block : 228 Whether the block is the fork block. 229 230 Returns 231 ------- 232 base_fee_per_gas : `Uint` 233 Base fee per gas for the block. 234 """ 235 if is_fork_block: 236 return Uint(INITIAL_BASE_FEE) 237 parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER 238 239 ensure( 240 check_gas_limit(block_gas_limit, parent_gas_limit), 241 InvalidBlock, 242 ) 243 244 if parent_gas_used == parent_gas_target: 245 expected_base_fee_per_gas = parent_base_fee_per_gas 246 elif parent_gas_used > parent_gas_target: 247 gas_used_delta = parent_gas_used - parent_gas_target 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 = max( 253 target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR, 254 1, 255 ) 256 257 expected_base_fee_per_gas = ( 258 parent_base_fee_per_gas + base_fee_per_gas_delta 259 ) 260 else: 261 gas_used_delta = parent_gas_target - parent_gas_used 262 263 parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta 264 target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target 265 266 base_fee_per_gas_delta = ( 267 target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR 268 ) 269 270 expected_base_fee_per_gas = ( 271 parent_base_fee_per_gas - base_fee_per_gas_delta 272 ) 273 274 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. is_fork_block : Whether the block is the fork block.
Returns
base_fee_per_gas : Uint
Base fee per gas for the block.
277def validate_header(header: Header, parent_header: Header) -> None: 278 """ 279 Verifies a block header. 280 281 In order to consider a block's header valid, the logic for the 282 quantities in the header should match the logic for the block itself. 283 For example the header timestamp should be greater than the block's parent 284 timestamp because the block was created *after* the parent block. 285 Additionally, the block's number should be directly following the parent 286 block's number since it is the next block in the sequence. 287 288 Parameters 289 ---------- 290 header : 291 Header to check for correctness. 292 parent_header : 293 Parent Header of the header to check for correctness 294 """ 295 ensure(header.gas_used <= header.gas_limit, InvalidBlock) 296 297 is_fork_block = header.number == FORK_CRITERIA.block_number 298 expected_base_fee_per_gas = calculate_base_fee_per_gas( 299 header.gas_limit, 300 parent_header.gas_limit, 301 parent_header.gas_used, 302 parent_header.base_fee_per_gas, 303 is_fork_block, 304 ) 305 306 ensure(expected_base_fee_per_gas == header.base_fee_per_gas, InvalidBlock) 307 308 parent_has_ommers = parent_header.ommers_hash != EMPTY_OMMER_HASH 309 ensure(header.timestamp > parent_header.timestamp, InvalidBlock) 310 ensure(header.number == parent_header.number + 1, InvalidBlock) 311 ensure(len(header.extra_data) <= 32, InvalidBlock) 312 313 block_difficulty = calculate_block_difficulty( 314 header.number, 315 header.timestamp, 316 parent_header.timestamp, 317 parent_header.difficulty, 318 parent_has_ommers, 319 ) 320 ensure(header.difficulty == block_difficulty, InvalidBlock) 321 322 block_parent_hash = keccak256(rlp.encode(parent_header)) 323 ensure(header.parent_hash == block_parent_hash, InvalidBlock) 324 325 validate_proof_of_work(header)
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
328def generate_header_hash_for_pow(header: Header) -> Hash32: 329 """ 330 Generate rlp hash of the header which is to be used for Proof-of-Work 331 verification. 332 333 In other words, the PoW artefacts `mix_digest` and `nonce` are ignored 334 while calculating this hash. 335 336 A particular PoW is valid for a single hash, that hash is computed by 337 this function. The `nonce` and `mix_digest` are omitted from this hash 338 because they are being changed by miners in their search for a sufficient 339 proof-of-work. 340 341 Parameters 342 ---------- 343 header : 344 The header object for which the hash is to be generated. 345 346 Returns 347 ------- 348 hash : `Hash32` 349 The PoW valid rlp hash of the passed in header. 350 """ 351 header_data_without_pow_artefacts = [ 352 header.parent_hash, 353 header.ommers_hash, 354 header.coinbase, 355 header.state_root, 356 header.transactions_root, 357 header.receipt_root, 358 header.bloom, 359 header.difficulty, 360 header.number, 361 header.gas_limit, 362 header.gas_used, 363 header.timestamp, 364 header.extra_data, 365 header.base_fee_per_gas, 366 ] 367 368 return rlp.rlp_hash(header_data_without_pow_artefacts)
Generate rlp hash of the header which is to be used for Proof-of-Work verification.
In other words, the PoW artefacts mix_digest
and nonce
are ignored
while calculating this hash.
A particular PoW is valid for a single hash, that hash is computed by
this function. The nonce
and mix_digest
are omitted from this hash
because they are being changed by miners in their search for a sufficient
proof-of-work.
Parameters
header : The header object for which the hash is to be generated.
Returns
hash : Hash32
The PoW valid rlp hash of the passed in header.
371def validate_proof_of_work(header: Header) -> None: 372 """ 373 Validates the Proof of Work constraints. 374 375 In order to verify that a miner's proof-of-work is valid for a block, a 376 ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` 377 hash function. The mix digest is a hash of the header and the nonce that 378 is passed through and it confirms whether or not proof-of-work was done 379 on the correct block. The result is the actual hash value of the block. 380 381 Parameters 382 ---------- 383 header : 384 Header of interest. 385 """ 386 header_hash = generate_header_hash_for_pow(header) 387 # TODO: Memoize this somewhere and read from that data instead of 388 # calculating cache for every block validation. 389 cache = generate_cache(header.number) 390 mix_digest, result = hashimoto_light( 391 header_hash, header.nonce, cache, dataset_size(header.number) 392 ) 393 394 ensure(mix_digest == header.mix_digest, InvalidBlock) 395 ensure( 396 Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty), 397 InvalidBlock, 398 )
Validates the Proof of Work constraints.
In order to verify that a miner's proof-of-work is valid for a block, a
mix-digest
and result
are calculated using the hashimoto_light
hash function. The mix digest is a hash of the header and the nonce that
is passed through and it confirms whether or not proof-of-work was done
on the correct block. The result is the actual hash value of the block.
Parameters
header : Header of interest.
401def check_transaction( 402 tx: Transaction, 403 base_fee_per_gas: Uint, 404 gas_available: Uint, 405 chain_id: U64, 406) -> Tuple[Address, Uint]: 407 """ 408 Check if the transaction is includable in the block. 409 410 Parameters 411 ---------- 412 tx : 413 The transaction. 414 base_fee_per_gas : 415 The block base fee. 416 gas_available : 417 The gas remaining in the block. 418 chain_id : 419 The ID of the current chain. 420 421 Returns 422 ------- 423 sender_address : 424 The sender of the transaction. 425 effective_gas_price : 426 The price to charge for gas when the transaction is executed. 427 428 Raises 429 ------ 430 InvalidBlock : 431 If the transaction is not includable. 432 """ 433 ensure(tx.gas <= gas_available, InvalidBlock) 434 sender_address = recover_sender(chain_id, tx) 435 436 if isinstance(tx, FeeMarketTransaction): 437 ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock) 438 ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock) 439 440 priority_fee_per_gas = min( 441 tx.max_priority_fee_per_gas, 442 tx.max_fee_per_gas - base_fee_per_gas, 443 ) 444 effective_gas_price = priority_fee_per_gas + base_fee_per_gas 445 else: 446 ensure(tx.gas_price >= base_fee_per_gas, InvalidBlock) 447 effective_gas_price = tx.gas_price 448 449 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.
452def make_receipt( 453 tx: Transaction, 454 error: Optional[Exception], 455 cumulative_gas_used: Uint, 456 logs: Tuple[Log, ...], 457) -> Union[Bytes, Receipt]: 458 """ 459 Make the receipt for a transaction that was executed. 460 461 Parameters 462 ---------- 463 tx : 464 The executed transaction. 465 error : 466 Error in the top level frame of the transaction, if any. 467 cumulative_gas_used : 468 The total gas used so far in the block after the transaction was 469 executed. 470 logs : 471 The logs produced by the transaction. 472 473 Returns 474 ------- 475 receipt : 476 The receipt for the transaction. 477 """ 478 receipt = Receipt( 479 succeeded=error is None, 480 cumulative_gas_used=cumulative_gas_used, 481 bloom=logs_bloom(logs), 482 logs=logs, 483 ) 484 485 if isinstance(tx, AccessListTransaction): 486 return b"\x01" + rlp.encode(receipt) 487 elif isinstance(tx, FeeMarketTransaction): 488 return b"\x02" + rlp.encode(receipt) 489 else: 490 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.
493def apply_body( 494 state: State, 495 block_hashes: List[Hash32], 496 coinbase: Address, 497 block_number: Uint, 498 base_fee_per_gas: Uint, 499 block_gas_limit: Uint, 500 block_time: U256, 501 block_difficulty: Uint, 502 transactions: Tuple[Union[LegacyTransaction, Bytes], ...], 503 ommers: Tuple[Header, ...], 504 chain_id: U64, 505) -> Tuple[Uint, Root, Root, Bloom, State]: 506 """ 507 Executes a block. 508 509 Many of the contents of a block are stored in data structures called 510 tries. There is a transactions trie which is similar to a ledger of the 511 transactions stored in the current block. There is also a receipts trie 512 which stores the results of executing a transaction, like the post state 513 and gas used. This function creates and executes the block that is to be 514 added to the chain. 515 516 Parameters 517 ---------- 518 state : 519 Current account state. 520 block_hashes : 521 List of hashes of the previous 256 blocks in the order of 522 increasing block number. 523 coinbase : 524 Address of account which receives block reward and transaction fees. 525 block_number : 526 Position of the block within the chain. 527 base_fee_per_gas : 528 Base fee per gas of within the block. 529 block_gas_limit : 530 Initial amount of gas available for execution in this block. 531 block_time : 532 Time the block was produced, measured in seconds since the epoch. 533 block_difficulty : 534 Difficulty of the block. 535 transactions : 536 Transactions included in the block. 537 ommers : 538 Headers of ancestor blocks which are not direct parents (formerly 539 uncles.) 540 chain_id : 541 ID of the executing chain. 542 543 Returns 544 ------- 545 block_gas_used : `ethereum.base_types.Uint` 546 Gas used for executing all transactions. 547 transactions_root : `ethereum.fork_types.Root` 548 Trie root of all the transactions in the block. 549 receipt_root : `ethereum.fork_types.Root` 550 Trie root of all the receipts in the block. 551 block_logs_bloom : `Bloom` 552 Logs bloom of all the logs included in all the transactions of the 553 block. 554 state : `ethereum.fork_types.State` 555 State after all transactions have been executed. 556 """ 557 gas_available = block_gas_limit 558 transactions_trie: Trie[ 559 Bytes, Optional[Union[Bytes, LegacyTransaction]] 560 ] = Trie(secured=False, default=None) 561 receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie( 562 secured=False, default=None 563 ) 564 block_logs: Tuple[Log, ...] = () 565 566 for i, tx in enumerate(map(decode_transaction, transactions)): 567 trie_set( 568 transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx) 569 ) 570 571 sender_address, effective_gas_price = check_transaction( 572 tx, base_fee_per_gas, gas_available, chain_id 573 ) 574 575 env = vm.Environment( 576 caller=sender_address, 577 origin=sender_address, 578 block_hashes=block_hashes, 579 coinbase=coinbase, 580 number=block_number, 581 gas_limit=block_gas_limit, 582 base_fee_per_gas=base_fee_per_gas, 583 gas_price=effective_gas_price, 584 time=block_time, 585 difficulty=block_difficulty, 586 state=state, 587 chain_id=chain_id, 588 traces=[], 589 ) 590 591 gas_used, logs, error = process_transaction(env, tx) 592 gas_available -= gas_used 593 594 receipt = make_receipt( 595 tx, error, (block_gas_limit - gas_available), logs 596 ) 597 598 trie_set( 599 receipts_trie, 600 rlp.encode(Uint(i)), 601 receipt, 602 ) 603 604 block_logs += logs 605 606 pay_rewards(state, block_number, coinbase, ommers) 607 608 block_gas_used = block_gas_limit - gas_available 609 610 block_logs_bloom = logs_bloom(block_logs) 611 612 return ( 613 block_gas_used, 614 root(transactions_trie), 615 root(receipts_trie), 616 block_logs_bloom, 617 state, 618 )
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. block_difficulty : Difficulty of the block. 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.
621def validate_ommers( 622 ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain 623) -> None: 624 """ 625 Validates the ommers mentioned in the block. 626 627 An ommer block is a block that wasn't canonically added to the 628 blockchain because it wasn't validated as fast as the canonical block 629 but was mined at the same time. 630 631 To be considered valid, the ommers must adhere to the rules defined in 632 the Ethereum protocol. The maximum amount of ommers is 2 per block and 633 there cannot be duplicate ommers in a block. Many of the other ommer 634 constraints are listed in the in-line comments of this function. 635 636 Parameters 637 ---------- 638 ommers : 639 List of ommers mentioned in the current block. 640 block_header: 641 The header of current block. 642 chain : 643 History and current state. 644 """ 645 block_hash = rlp.rlp_hash(block_header) 646 647 ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock) 648 649 if len(ommers) == 0: 650 # Nothing to validate 651 return 652 653 # Check that each ommer satisfies the constraints of a header 654 for ommer in ommers: 655 ensure(1 <= ommer.number < block_header.number, InvalidBlock) 656 ommer_parent_header = chain.blocks[ 657 -(block_header.number - ommer.number) - 1 658 ].header 659 validate_header(ommer, ommer_parent_header) 660 661 # Check that there can be only at most 2 ommers for a block. 662 ensure(len(ommers) <= 2, InvalidBlock) 663 664 ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers] 665 # Check that there are no duplicates in the ommers of current block 666 ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock) 667 668 recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :] 669 recent_canonical_block_hashes = { 670 rlp.rlp_hash(block.header) for block in recent_canonical_blocks 671 } 672 recent_ommers_hashes: Set[Hash32] = set() 673 for block in recent_canonical_blocks: 674 recent_ommers_hashes = recent_ommers_hashes.union( 675 {rlp.rlp_hash(ommer) for ommer in block.ommers} 676 ) 677 678 for ommer_index, ommer in enumerate(ommers): 679 ommer_hash = ommers_hashes[ommer_index] 680 # The current block shouldn't be the ommer 681 ensure(ommer_hash != block_hash, InvalidBlock) 682 683 # Ommer shouldn't be one of the recent canonical blocks 684 ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock) 685 686 # Ommer shouldn't be one of the uncles mentioned in the recent 687 # canonical blocks 688 ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock) 689 690 # Ommer age with respect to the current block. For example, an age of 691 # 1 indicates that the ommer is a sibling of previous block. 692 ommer_age = block_header.number - ommer.number 693 ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock) 694 695 ensure( 696 ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock 697 ) 698 ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock)
Validates the ommers mentioned in the block.
An ommer block is a block that wasn't canonically added to the blockchain because it wasn't validated as fast as the canonical block but was mined at the same time.
To be considered valid, the ommers must adhere to the rules defined in the Ethereum protocol. The maximum amount of ommers is 2 per block and there cannot be duplicate ommers in a block. Many of the other ommer constraints are listed in the in-line comments of this function.
Parameters
ommers : List of ommers mentioned in the current block. block_header: The header of current block. chain : History and current state.
701def pay_rewards( 702 state: State, 703 block_number: Uint, 704 coinbase: Address, 705 ommers: Tuple[Header, ...], 706) -> None: 707 """ 708 Pay rewards to the block miner as well as the ommers miners. 709 710 The miner of the canonical block is rewarded with the predetermined 711 block reward, ``BLOCK_REWARD``, plus a variable award based off of the 712 number of ommer blocks that were mined around the same time, and included 713 in the canonical block's header. An ommer block is a block that wasn't 714 added to the canonical blockchain because it wasn't validated as fast as 715 the accepted block but was mined at the same time. Although not all blocks 716 that are mined are added to the canonical chain, miners are still paid a 717 reward for their efforts. This reward is called an ommer reward and is 718 calculated based on the number associated with the ommer block that they 719 mined. 720 721 Parameters 722 ---------- 723 state : 724 Current account state. 725 block_number : 726 Position of the block within the chain. 727 coinbase : 728 Address of account which receives block reward and transaction fees. 729 ommers : 730 List of ommers mentioned in the current block. 731 """ 732 miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32)) 733 create_ether(state, coinbase, miner_reward) 734 735 for ommer in ommers: 736 # Ommer age with respect to the current block. 737 ommer_age = U256(block_number - ommer.number) 738 ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8 739 create_ether(state, ommer.coinbase, ommer_miner_reward)
Pay rewards to the block miner as well as the ommers miners.
The miner of the canonical block is rewarded with the predetermined
block reward, BLOCK_REWARD
, plus a variable award based off of the
number of ommer blocks that were mined around the same time, and included
in the canonical block's header. An ommer block is a block that wasn't
added to the canonical blockchain because it wasn't validated as fast as
the accepted block but was mined at the same time. Although not all blocks
that are mined are added to the canonical chain, miners are still paid a
reward for their efforts. This reward is called an ommer reward and is
calculated based on the number associated with the ommer block that they
mined.
Parameters
state : Current account state. block_number : Position of the block within the chain. coinbase : Address of account which receives block reward and transaction fees. ommers : List of ommers mentioned in the current block.
742def process_transaction( 743 env: vm.Environment, tx: Transaction 744) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]: 745 """ 746 Execute a transaction against the provided environment. 747 748 This function processes the actions needed to execute a transaction. 749 It decrements the sender's account after calculating the gas fee and 750 refunds them the proper amount after execution. Calling contracts, 751 deploying code, and incrementing nonces are all examples of actions that 752 happen within this function or from a call made within this function. 753 754 Accounts that are marked for deletion are processed and destroyed after 755 execution. 756 757 Parameters 758 ---------- 759 env : 760 Environment for the Ethereum Virtual Machine. 761 tx : 762 Transaction to execute. 763 764 Returns 765 ------- 766 gas_left : `ethereum.base_types.U256` 767 Remaining gas after execution. 768 logs : `Tuple[ethereum.fork_types.Log, ...]` 769 Logs generated during execution. 770 """ 771 ensure(validate_transaction(tx), InvalidBlock) 772 773 sender = env.origin 774 sender_account = get_account(env.state, sender) 775 776 if isinstance(tx, FeeMarketTransaction): 777 max_gas_fee = tx.gas * tx.max_fee_per_gas 778 else: 779 max_gas_fee = tx.gas * tx.gas_price 780 781 ensure(sender_account.nonce == tx.nonce, InvalidBlock) 782 ensure(sender_account.balance >= max_gas_fee + tx.value, InvalidBlock) 783 ensure(sender_account.code == bytearray(), InvalidBlock) 784 785 effective_gas_fee = tx.gas * env.gas_price 786 787 gas = tx.gas - calculate_intrinsic_cost(tx) 788 increment_nonce(env.state, sender) 789 790 sender_balance_after_gas_fee = sender_account.balance - effective_gas_fee 791 set_account_balance(env.state, sender, sender_balance_after_gas_fee) 792 793 preaccessed_addresses = set() 794 preaccessed_storage_keys = set() 795 if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): 796 for address, keys in tx.access_list: 797 preaccessed_addresses.add(address) 798 for key in keys: 799 preaccessed_storage_keys.add((address, key)) 800 801 message = prepare_message( 802 sender, 803 tx.to, 804 tx.value, 805 tx.data, 806 gas, 807 env, 808 preaccessed_addresses=frozenset(preaccessed_addresses), 809 preaccessed_storage_keys=frozenset(preaccessed_storage_keys), 810 ) 811 812 output = process_message_call(message, env) 813 814 gas_used = tx.gas - output.gas_left 815 gas_refund = min(gas_used // 5, output.refund_counter) 816 gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price 817 818 # For non-1559 transactions env.gas_price == tx.gas_price 819 priority_fee_per_gas = env.gas_price - env.base_fee_per_gas 820 transaction_fee = ( 821 tx.gas - output.gas_left - gas_refund 822 ) * priority_fee_per_gas 823 824 total_gas_used = gas_used - gas_refund 825 826 # refund gas 827 sender_balance_after_refund = ( 828 get_account(env.state, sender).balance + gas_refund_amount 829 ) 830 set_account_balance(env.state, sender, sender_balance_after_refund) 831 832 # transfer miner fees 833 coinbase_balance_after_mining_fee = ( 834 get_account(env.state, env.coinbase).balance + transaction_fee 835 ) 836 if coinbase_balance_after_mining_fee != 0: 837 set_account_balance( 838 env.state, env.coinbase, coinbase_balance_after_mining_fee 839 ) 840 elif account_exists_and_is_empty(env.state, env.coinbase): 841 destroy_account(env.state, env.coinbase) 842 843 for address in output.accounts_to_delete: 844 destroy_account(env.state, address) 845 846 for address in output.touched_accounts: 847 if account_exists_and_is_empty(env.state, address): 848 destroy_account(env.state, address) 849 850 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.
853def validate_transaction(tx: Transaction) -> bool: 854 """ 855 Verifies a transaction. 856 857 The gas in a transaction gets used to pay for the intrinsic cost of 858 operations, therefore if there is insufficient gas then it would not 859 be possible to execute a transaction and it will be declared invalid. 860 861 Additionally, the nonce of a transaction must not equal or exceed the 862 limit defined in `EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>`_. 863 In practice, defining the limit as ``2**64-1`` has no impact because 864 sending ``2**64-1`` transactions is improbable. It's not strictly 865 impossible though, ``2**64-1`` transactions is the entire capacity of the 866 Ethereum blockchain at 2022 gas limits for a little over 22 years. 867 868 Parameters 869 ---------- 870 tx : 871 Transaction to validate. 872 873 Returns 874 ------- 875 verified : `bool` 876 True if the transaction can be executed, or False otherwise. 877 """ 878 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.
881def calculate_intrinsic_cost(tx: Transaction) -> Uint: 882 """ 883 Calculates the gas that is charged before execution is started. 884 885 The intrinsic cost of the transaction is charged before execution has 886 begun. Functions/operations in the EVM cost money to execute so this 887 intrinsic cost is for the operations that need to be paid for as part of 888 the transaction. Data transfer, for example, is part of this intrinsic 889 cost. It costs ether to send data over the wire and that ether is 890 accounted for in the intrinsic cost calculated in this function. This 891 intrinsic cost must be calculated and paid for before execution in order 892 for all operations to be implemented. 893 894 Parameters 895 ---------- 896 tx : 897 Transaction to compute the intrinsic cost of. 898 899 Returns 900 ------- 901 verified : `ethereum.base_types.Uint` 902 The intrinsic cost of the transaction. 903 """ 904 data_cost = 0 905 906 for byte in tx.data: 907 if byte == 0: 908 data_cost += TX_DATA_COST_PER_ZERO 909 else: 910 data_cost += TX_DATA_COST_PER_NON_ZERO 911 912 if tx.to == Bytes0(b""): 913 create_cost = TX_CREATE_COST 914 else: 915 create_cost = 0 916 917 access_list_cost = 0 918 if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): 919 for _address, keys in tx.access_list: 920 access_list_cost += TX_ACCESS_LIST_ADDRESS_COST 921 access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST 922 923 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.
926def recover_sender(chain_id: U64, tx: Transaction) -> Address: 927 """ 928 Extracts the sender address from a transaction. 929 930 The v, r, and s values are the three parts that make up the signature 931 of a transaction. In order to recover the sender of a transaction the two 932 components needed are the signature (``v``, ``r``, and ``s``) and the 933 signing hash of the transaction. The sender's public key can be obtained 934 with these two values and therefore the sender address can be retrieved. 935 936 Parameters 937 ---------- 938 tx : 939 Transaction of interest. 940 chain_id : 941 ID of the executing chain. 942 943 Returns 944 ------- 945 sender : `ethereum.fork_types.Address` 946 The address of the account that signed the transaction. 947 """ 948 r, s = tx.r, tx.s 949 950 ensure(0 < r and r < SECP256K1N, InvalidBlock) 951 ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock) 952 953 if isinstance(tx, LegacyTransaction): 954 v = tx.v 955 if v == 27 or v == 28: 956 public_key = secp256k1_recover( 957 r, s, v - 27, signing_hash_pre155(tx) 958 ) 959 else: 960 ensure( 961 v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock 962 ) 963 public_key = secp256k1_recover( 964 r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) 965 ) 966 elif isinstance(tx, AccessListTransaction): 967 public_key = secp256k1_recover( 968 r, s, tx.y_parity, signing_hash_2930(tx) 969 ) 970 elif isinstance(tx, FeeMarketTransaction): 971 public_key = secp256k1_recover( 972 r, s, tx.y_parity, signing_hash_1559(tx) 973 ) 974 975 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.
978def signing_hash_pre155(tx: LegacyTransaction) -> Hash32: 979 """ 980 Compute the hash of a transaction used in a legacy (pre EIP 155) signature. 981 982 Parameters 983 ---------- 984 tx : 985 Transaction of interest. 986 987 Returns 988 ------- 989 hash : `ethereum.crypto.hash.Hash32` 990 Hash of the transaction. 991 """ 992 return keccak256( 993 rlp.encode( 994 ( 995 tx.nonce, 996 tx.gas_price, 997 tx.gas, 998 tx.to, 999 tx.value, 1000 tx.data, 1001 ) 1002 ) 1003 )
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.
1006def signing_hash_155(tx: LegacyTransaction, chain_id: U64) -> Hash32: 1007 """ 1008 Compute the hash of a transaction used in a EIP 155 signature. 1009 1010 Parameters 1011 ---------- 1012 tx : 1013 Transaction of interest. 1014 chain_id : 1015 The id of the current chain. 1016 1017 Returns 1018 ------- 1019 hash : `ethereum.crypto.hash.Hash32` 1020 Hash of the transaction. 1021 """ 1022 return keccak256( 1023 rlp.encode( 1024 ( 1025 tx.nonce, 1026 tx.gas_price, 1027 tx.gas, 1028 tx.to, 1029 tx.value, 1030 tx.data, 1031 chain_id, 1032 Uint(0), 1033 Uint(0), 1034 ) 1035 ) 1036 )
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.
1039def signing_hash_2930(tx: AccessListTransaction) -> Hash32: 1040 """ 1041 Compute the hash of a transaction used in a EIP 2930 signature. 1042 1043 Parameters 1044 ---------- 1045 tx : 1046 Transaction of interest. 1047 1048 Returns 1049 ------- 1050 hash : `ethereum.crypto.hash.Hash32` 1051 Hash of the transaction. 1052 """ 1053 return keccak256( 1054 b"\x01" 1055 + rlp.encode( 1056 ( 1057 tx.chain_id, 1058 tx.nonce, 1059 tx.gas_price, 1060 tx.gas, 1061 tx.to, 1062 tx.value, 1063 tx.data, 1064 tx.access_list, 1065 ) 1066 ) 1067 )
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.
1070def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32: 1071 """ 1072 Compute the hash of a transaction used in a EIP 1559 signature. 1073 1074 Parameters 1075 ---------- 1076 tx : 1077 Transaction of interest. 1078 1079 Returns 1080 ------- 1081 hash : `ethereum.crypto.hash.Hash32` 1082 Hash of the transaction. 1083 """ 1084 return keccak256( 1085 b"\x02" 1086 + rlp.encode( 1087 ( 1088 tx.chain_id, 1089 tx.nonce, 1090 tx.max_priority_fee_per_gas, 1091 tx.max_fee_per_gas, 1092 tx.gas, 1093 tx.to, 1094 tx.value, 1095 tx.data, 1096 tx.access_list, 1097 ) 1098 ) 1099 )
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.
1102def compute_header_hash(header: Header) -> Hash32: 1103 """ 1104 Computes the hash of a block header. 1105 1106 The header hash of a block is the canonical hash that is used to refer 1107 to a specific block and completely distinguishes a block from another. 1108 1109 ``keccak256`` is a function that produces a 256 bit hash of any input. 1110 It also takes in any number of bytes as an input and produces a single 1111 hash for them. A hash is a completely unique output for a single input. 1112 So an input corresponds to one unique hash that can be used to identify 1113 the input exactly. 1114 1115 Prior to using the ``keccak256`` hash function, the header must be 1116 encoded using the Recursive-Length Prefix. See :ref:`rlp`. 1117 RLP encoding the header converts it into a space-efficient format that 1118 allows for easy transfer of data between nodes. The purpose of RLP is to 1119 encode arbitrarily nested arrays of binary data, and RLP is the primary 1120 encoding method used to serialize objects in Ethereum's execution layer. 1121 The only purpose of RLP is to encode structure; encoding specific data 1122 types (e.g. strings, floats) is left up to higher-order protocols. 1123 1124 Parameters 1125 ---------- 1126 header : 1127 Header of interest. 1128 1129 Returns 1130 ------- 1131 hash : `ethereum.crypto.hash.Hash32` 1132 Hash of the header. 1133 """ 1134 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.
1137def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: 1138 """ 1139 Validates the gas limit for a block. 1140 1141 The bounds of the gas limit, ``max_adjustment_delta``, is set as the 1142 quotient of the parent block's gas limit and the 1143 ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is 1144 passed through as a parameter is greater than or equal to the *sum* of 1145 the parent's gas and the adjustment delta then the limit for gas is too 1146 high and fails this function's check. Similarly, if the limit is less 1147 than or equal to the *difference* of the parent's gas and the adjustment 1148 delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's 1149 check fails because the gas limit doesn't allow for a sufficient or 1150 reasonable amount of gas to be used on a block. 1151 1152 Parameters 1153 ---------- 1154 gas_limit : 1155 Gas limit to validate. 1156 1157 parent_gas_limit : 1158 Gas limit of the parent block. 1159 1160 Returns 1161 ------- 1162 check : `bool` 1163 True if gas limit constraints are satisfied, False otherwise. 1164 """ 1165 max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR 1166 if gas_limit >= parent_gas_limit + max_adjustment_delta: 1167 return False 1168 if gas_limit <= parent_gas_limit - max_adjustment_delta: 1169 return False 1170 if gas_limit < GAS_LIMIT_MINIMUM: 1171 return False 1172 1173 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.
1176def calculate_block_difficulty( 1177 block_number: Uint, 1178 block_timestamp: U256, 1179 parent_timestamp: U256, 1180 parent_difficulty: Uint, 1181 parent_has_ommers: bool, 1182) -> Uint: 1183 """ 1184 Computes difficulty of a block using its header and parent header. 1185 1186 The difficulty is determined by the time the block was created after its 1187 parent. The ``offset`` is calculated using the parent block's difficulty, 1188 ``parent_difficulty``, and the timestamp between blocks. This offset is 1189 then added to the parent difficulty and is stored as the ``difficulty`` 1190 variable. If the time between the block and its parent is too short, the 1191 offset will result in a positive number thus making the sum of 1192 ``parent_difficulty`` and ``offset`` to be a greater value in order to 1193 avoid mass forking. But, if the time is long enough, then the offset 1194 results in a negative value making the block less difficult than 1195 its parent. 1196 1197 The base standard for a block's difficulty is the predefined value 1198 set for the genesis block since it has no parent. So, a block 1199 can't be less difficult than the genesis block, therefore each block's 1200 difficulty is set to the maximum value between the calculated 1201 difficulty and the ``GENESIS_DIFFICULTY``. 1202 1203 Parameters 1204 ---------- 1205 block_number : 1206 Block number of the block. 1207 block_timestamp : 1208 Timestamp of the block. 1209 parent_timestamp : 1210 Timestamp of the parent block. 1211 parent_difficulty : 1212 difficulty of the parent block. 1213 parent_has_ommers: 1214 does the parent have ommers. 1215 1216 Returns 1217 ------- 1218 difficulty : `ethereum.base_types.Uint` 1219 Computed difficulty for a block. 1220 """ 1221 offset = ( 1222 int(parent_difficulty) 1223 // 2048 1224 * max( 1225 (2 if parent_has_ommers else 1) 1226 - int(block_timestamp - parent_timestamp) // 9, 1227 -99, 1228 ) 1229 ) 1230 difficulty = int(parent_difficulty) + offset 1231 # Historical Note: The difficulty bomb was not present in Ethereum at the 1232 # start of Frontier, but was added shortly after launch. However since the 1233 # bomb has no effect prior to block 200000 we pretend it existed from 1234 # genesis. 1235 # See https://github.com/ethereum/go-ethereum/pull/1588 1236 num_bomb_periods = ((int(block_number) - BOMB_DELAY_BLOCKS) // 100000) - 2 1237 if num_bomb_periods >= 0: 1238 difficulty += 2**num_bomb_periods 1239 1240 # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding 1241 # the bomb. This bug does not matter because the difficulty is always much 1242 # greater than `MINIMUM_DIFFICULTY` on Mainnet. 1243 return Uint(max(difficulty, MINIMUM_DIFFICULTY))
Computes difficulty of a block using its header and parent header.
The difficulty is determined by the time the block was created after its
parent. The offset
is calculated using the parent block's difficulty,
parent_difficulty
, and the timestamp between blocks. This offset is
then added to the parent difficulty and is stored as the difficulty
variable. If the time between the block and its parent is too short, the
offset will result in a positive number thus making the sum of
parent_difficulty
and offset
to be a greater value in order to
avoid mass forking. But, if the time is long enough, then the offset
results in a negative value making the block less difficult than
its parent.
The base standard for a block's difficulty is the predefined value
set for the genesis block since it has no parent. So, a block
can't be less difficult than the genesis block, therefore each block's
difficulty is set to the maximum value between the calculated
difficulty and the GENESIS_DIFFICULTY
.
Parameters
block_number : Block number of the block. block_timestamp : Timestamp of the block. parent_timestamp : Timestamp of the parent block. parent_difficulty : difficulty of the parent block. parent_has_ommers: does the parent have ommers.
Returns
difficulty : ethereum.base_types.Uint
Computed difficulty for a block.