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