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